Why does my program stop after passing data from c++ dll to c# several times? (There's no error message)

耗尽温柔 提交于 2020-01-24 22:10:25

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!