ONNXRuntime程序运行两次后崩溃



我正在编写一个应该在VS2013中运行的程序,该程序接收两个图像,用C++在ONNX模型中运行,并返回模型的输出

因为我使用的是图像,所以我在VS2019中编写程序,并创建一个将在VS2013 中运行的DLL

我能够使用它与一个图像,它工作得很好。当我尝试与两个映像一起使用时,运行一次程序可以很好地工作,但如果我尝试连续执行两次,在尝试删除std::wstring时,它会因断言而崩溃。我试图追踪它的起源,但我能找到的最接近的是Microsoft Visual Studio2019EnterpriseVCToolsMSVC14.29.30133crtsrcvcruntime,在函数中

_CRT_SECURITYCRITICAL_ATTRIBUTE
void __CRTDECL operator delete(void* const block, size_t const) noexcept
{
operator delete(block);
}

VS2019中的代码是:

#include <iostream>
#include <fstream>
#include <Windows.h>
Mat MeanOverChannels(Mat m) {
/*
* input: cv::Mat with more than one channel (=3)
* output: cv::Mat with one channel, that is the average over channels
*/
Size size = m.size();
int channels = m.channels();
Mat res(size, CV_64FC1);
for (int i = 0; i < size.height; i++) {
for (int j = 0; j < size.width; j++) {
double avg = 0;
auto cur = m.at<Vec3b>(i, j);
for (int c = 0; c < channels; c++)
{
avg += cur[c];
}
avg /= channels;
res.at<double>(i, j) = avg;
}
}
return res;
}
cv::Mat GetInputNormalized(string imgpath
, int& original_height, int& original_width
, int input_height, int input_width) {
/*
* input: path to image, and refernces to save the origianl size
* output: image from the path after resizing and normalizing
*/
//read input
Mat img = imread(imgpath, IMREAD_COLOR);  // can use IMREAD_UNCHANGED
Size s = img.size();
original_height = s.height;
original_width = s.width;
//mean over axis=2, you can comment out if it is not needed for you
Mat img_mean = MeanOverChannels(img);

//resize down
int down_width = input_width;
int down_height = input_height;
Mat resized_down;
resize(img_mean, resized_down, Size(down_width, down_height), INTER_LINEAR);
//can return resized_down, from here you can customize the input
Mat img2float;
resized_down.convertTo(img2float, CV_64FC1);
//normalize pixels : p->(p-127.5)/127.5
Mat imgNorm = (img2float - 127.5) / 127.5;
return imgNorm;
}
bool Net::RunNet(std::wstring modelName, std::string inPath1, std::string inPath2, float& iRes) {
/*********this model assumes two inputs and one output************/
/////path to the onnx model/////
wchar_t buffer[MAX_PATH];
GetModuleFileNameW(NULL, buffer, MAX_PATH);
const wchar_t* endChar = LR"(\/)";
std::wstring::size_type pos = std::wstring(buffer).find_last_of(endChar);
std::wstring modelPath;
modelPath = std::wstring(buffer).substr(0, pos) + endChar + modelName;

bool success = false;
/////variables to run the model/////
Ort::Env env;
Ort::Session session{ env,  modelPath.c_str(), Ort::SessionOptions{} };
Ort::AllocatorWithDefaultOptions allocator;
auto memoryInfo = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
auto* inputName1 = session.GetInputName(0, allocator);
auto* inputName2 = session.GetInputName(1, allocator);
auto* outputName = session.GetOutputName(0, allocator);
array inputNames = { inputName1, inputName2 };
array outputNames = { outputName };
auto inputShape1 = session.GetInputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape();
auto inputShape2 = session.GetInputTypeInfo(1).GetTensorTypeAndShapeInfo().GetShape();
for (int i = 0;i < inputShape1.size(); ++i) {
inputShape1[i] = inputShape1[i] > 0 ? inputShape1[i] : 1; //in case inputShape[0] is -1 (None in python)
}
for (int i = 0;i < inputShape2.size(); ++i) {
inputShape2[i] = inputShape2[i] > 0 ? inputShape2[i] : 1; //in case inputShape[0] is -1 (None in python)
}
int input_height1 = inputShape1[1], input_width1 = inputShape1[2];
int input_height2 = inputShape2[1], input_width2 = inputShape2[2];
/////getting input to the net/////
Mat img1, img2;
int origHeight1, origWidth1
, origHeight2, origWidth2;
img1 = GetInputNormalized(inPath1
, origHeight1, origWidth1
, input_height1, input_width1
);
img2 = GetInputNormalized(inPath2
, origHeight2, origWidth2
, input_height2, input_width2
);
vf inputValues1 = MatTo1DVector(img1);
vf inputValues2 = MatTo1DVector(img2);
//// create the input tensor (this is not a deep copy!)
auto inputOnnxTensor1 = Ort::Value::CreateTensor<float>(memoryInfo,
inputValues1.data(), inputValues1.size(),
inputShape1.data(), inputShape1.size());
auto inputOnnxTensor2 = Ort::Value::CreateTensor<float>(memoryInfo,
inputValues2.data(), inputValues2.size(),
inputShape2.data(), inputShape2.size());
array input_tensor = { std::move(inputOnnxTensor1), std::move(inputOnnxTensor2) };

///////Executing the model/////
auto outputValues = session.Run(
Ort::RunOptions{ nullptr }, // e.g. set a verbosity level only for this run
inputNames.data(), input_tensor.data(), input_tensor.size(), // input to set
outputNames.data(), 1);                 // output to take 
auto& output1 = outputValues[0];
const auto* floats = output1.GetTensorMutableData<float>();
const auto floatsCount = output1.GetTensorTypeAndShapeInfo().GetElementCount();
float res = *floats;
iRes = res;

allocator.Free(inputName1);
allocator.Free(inputName2);
allocator.Free(outputName);
success = true;
return success;
}

我导出的是NetFactory的一个函数,它创建Net的unique_ptr,通过这个工厂我们创建Net的一个实例_net,然后我执行_net->RunNetSimCompare(modelName, inPath1, inPath2, res);

并在执行之后返回CCD_ 5。

问题出在哪里?

对于那些遇到同样问题的人来说,似乎将函数的签名更改为以下内容:

bool Net::RunNet(std::wstring&modelName, std::string&inPath1, std::string&inPath2, float&iRes)

修复

最新更新