Почему моя программа останавливается после передачи данных из c ++ dll в c # несколько раз? (Там нет сообщения об ошибке) - PullRequest
1 голос
/ 18 октября 2019

Я работаю над проектом, который требует использования файла dll для другой программы, написанной на c # (я не очень знаком с использованием C ++ / C #). Закончив разработку (?) Файла dll, я начал процесс тестирования (много раз запускал вызов функции из dll в C #, чтобы убедиться, что он работает нормально). Я спросил способ передачи данных из C ++ в C # здесь , и проблема в том, программа остановится без какого-либо сообщения об ошибке (я поставил try catch в моей программе) после вызова более 2 раз .

enter image description here

Я видел высказывание о том, что при повреждении памяти программа остановится на очень нормальной строке (например, std :: cout <<...). Я думаю, что моя ситуация похожа на поговорку ... </p>

А вот моя структура кода ...

//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("================================");
            }
        }
    }
}

Я пытался не возвращать результат из DLL в C #, этоможет работать около 100 раз (максимум я проверял). Поэтому я думаю, что проблема может быть в процессе передачи данных из dll в C # ...

Кстати, вот мое использование памяти при запуске программы ... enter image description here

Я искал много информации в интернете, но до сих пор не знаю, как решить эту проблему, поэтому любые советы или помощь действительно приветствуются!

(Заранее благодарен за то, что дочитал моебеспорядочное описание вопроса!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...