问题
I'm working on a project which required a dll file for another program written in c# to use (I'm not very familiar with the usage of C++/C#). After finishing the development(?) of the dll file, I started its testing process(run the function call from dll in C# for many times to ensure it works fine). I've asked the way to pass data from C++ to C# here, and the problem is, the program will stop without any error message(I've put try catch in my program) after calling it over 2 times.
I've seen a saying that if there's a memory corruption, the program will stop at a very normal line(e.g. std::cout << ...). I think my situation is similar to that saying...
And here's my code structure...
//dll.hpp
extern "C" LIB_API void inference(unsigned char* img_pointer, long data_len, cv::Mat*& res, int& img_count, int& mat_type_size, double params[2]);
extern "C" LIB_API void clear_mem(cv::Mat* res);
//dll.cpp
LIB_API void inference(unsigned char* img_pointer, long data_len, cv::Mat*& res, int& img_count, int& mat_type_size, double params[2])
{
try
{
img_count = 8;
mat_type_size = sizeof(cv::Mat);
res = new cv::Mat[img_count];
cv::Mat& img1 = res[0];
cv::Mat& img2 = res[1];
cv::Mat& img3 = res[2];
cv::Mat& img4 = res[3];
cv::Mat& img5 = res[4];
cv::Mat& img6 = res[5];
cv::Mat& img7 = res[6];
cv::Mat& img8 = res[7];
//some process to update img1~img8
std::cout << "res->" << res << std::endl;
std::cout << "===== finish inference process ===== >> " << (std::clock() - t_inf1) / (double)CLOCKS_PER_SEC << " s" << std::endl;
}
catch (const std::runtime_error& re)
{
std::cerr << "*** Runtime error: " << re.what() << std::endl;
return;
}
catch (const std::exception& ex)
{
std::cerr << "*** Error occurred: " << ex.what() << std::endl;
return;
}
catch (...)
{
std::cerr << "*** Unknown failure occurred... Possible memory corruption" << std::endl;
return;
}
}
LIB_API void clear_mem(cv::Mat* res)
{
try
{
std::cout << ">> In 'clear_mem'...." << std::endl;
std::cout << "res in clear_mem->" << res << std::endl;
delete[] res;
std::cout << ">> finish deleting res...." << std::endl;
}
catch (const std::runtime_error& re)
{
std::cerr << "*** Runtime error: " << re.what() << std::endl;
return;
}
catch (const std::exception& ex)
{
std::cerr << "*** Error occurred: " << ex.what() << std::endl;
return;
}
catch (...)
{
std::cerr << "*** Unknown failure occurred... Possible memory corruption" << std::endl;
return;
}
}
//test.cs
namespace Test_Unet_Console
{
class Program
{
[DllImport(@"D:\Coco\Code\C_plus_plus\unet_cpp_dll\x64\Release\unet_cpp_dll.dll")]
private static extern void inference(byte[] img, long data_len, out IntPtr images, ref int img_count, out int mat_type_size,
[In, MarshalAs(UnmanagedType.LPArray, SizeConst = 3)]double[] param);
[DllImport(@"D:\Coco\Code\C_plus_plus\unet_cpp_dll\x64\Release\unet_cpp_dll.dll")]
private static extern void init_inference();
[DllImport(@"D:\Coco\Code\C_plus_plus\unet_cpp_dll\x64\Release\unet_cpp_dll.dll")]
private static extern void clear_mem(IntPtr images);
static void Cppdll_inf(Bitmap image, out List<Mat> output_pic, double[] param, out IntPtr imgPtrs)
{
Console.WriteLine("before fmt");
ImageFormat fmt = new ImageFormat(image.RawFormat.Guid);
Console.WriteLine("before imageCodecInfo");
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == image.RawFormat.Guid);
//this is for situations, where the image is not read from disk, and is stored in the memory(e.g. image comes from a camera or snapshot)
if (imageCodecInfo == null)
{
fmt = ImageFormat.Jpeg;
Console.WriteLine("C# - imageCodecInfo is null");
}
Console.WriteLine("before MemoryStream");
using (MemoryStream ms = new MemoryStream())
{
try
{
Console.WriteLine("C# - before image.Save");
image.Save(ms, fmt);
Console.WriteLine("C# - finish image.Save");
byte[] image_byte_array = ms.ToArray();
Console.WriteLine("C# - finish reading pic");
int imgCount = 0;
inference(image_byte_array, ms.Length, out var imgPtrs, ref imgCount, out var matTypeSize, param);
output_pic = new List<Mat>();
for (int i = 0; i < imgCount; i++)
{
output_pic.Add(new Mat(IntPtr.Add(imgPtrs, i * matTypeSize)));
}
Console.WriteLine("finish getting value from imgPtrs.....");
}
catch (Exception ex)
{
throw ex;
}
}
}
// I've tried to add this in my code, but it will cause some error(I didn't record it...)
static void clear()
{
Console.WriteLine("start gc collect");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("finish gc collect in clear");
}
static void show_result(List<Mat> pic_list)
{
for (int i = 0; i < pic_list.Count; i++)
{
Console.WriteLine(i);
Cv2.ImShow("test", pic_list[i]);
Cv2.WaitKey(500);
}
Cv2.DestroyAllWindows();
Console.WriteLine("finish showing pic");
}
static void Main()
{
Bitmap image1 = new Bitmap("C:\\Users\\Coco\\Desktop\\(3).png");
double[] param = { 0.7, 20 }; //{ VI_threshold, area_threshold }
Console.WriteLine(">>> Initializing from C# =======");
init_inference(); // >> initialization of models
Console.WriteLine(">>> Finish initializing from C# ======");
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i);
List<Mat> result;
IntPtr imgPtrs;
Cppdll_inf(image1, out result, param, out imgPtrs); // inference of picture
Console.WriteLine(">>> Finish image1 C# ======");
show_result(result); // showing pic to check if result is correct
clear_mem(imgPtrs); // clean the memory send from dll(?
result.Clear();
Console.WriteLine(">>> Finish result.Clear() ======");
Console.WriteLine("================================");
}
}
}
}
I've tried not to return the result from dll to C#, it can run about 100 times(the maximum I've tested). So I think the problem might be the process when passing data from dll to C#...
By the way, here's my memory usage when running the program...
I've searched many info on the internet, but I still have no idea how to fix this problem, so any advise or help is really appreciated!
(Thanks in advance for finish reading my messy question description! )
来源:https://stackoverflow.com/questions/58450923/why-does-my-program-stop-after-passing-data-from-c-dll-to-c-sharp-several-time