Marshal.Copy пытался читать или записывать защищенную память в случайное время - PullRequest
0 голосов
/ 02 ноября 2018

У меня проблема с моим кодом, где он работает правильно, но в случайное время вызов функции Marshal.Copy дает мне исключение нарушения прав доступа. Моя программа получает изображение с рентгеновского сканера. Рентгеновский сканер помещает изображение в память и дает мне указатель, откуда я получаю эту картинку. Я использую Marsharl.Copy, чтобы поместить информацию в указателе в байтовый массив размером 2 * Ширина (# x пикселей) * Высота (# число Y пикселей) и обработать ее.

вот функция, которая вызывается каждые 1,5 с или около того, чтобы получить изображение

public void GetLiveImage()
{
   VirtCp.SLivePrms lp = new VirtCp.SLivePrms();
   Mode mode = Modes.Where(x => x.ModeNumber == CurrentMode).First<Mode>();
   MemoryError = false;
   OkProceed = false;
   int errCode = 0;
   int timeout = 0;
   xPixelSize = (int)mode.ColumnsPerFrame;
   yPixelSize = (int)mode.LinesPerFrame;

   imageSize = 2 * xPixelSize * yPixelSize;

   IntPtr image = Marshal.AllocHGlobal(imageSize);

   logger.WriteLine("Calling function to obtain image");

   errCode = VirtCp.VipFluoroGetPrms(ref lp); // this function from the scanner dll gives points me to the data of the image

   while (errCode != (int)HCPError.HCP_NO_ERR)
   {
      timeout++;
      if (timeout > 350000)
      {
         logger.WriteLine("There are problems with detector:" + HCPErrorText.GetErrorText(errCode));
         OkProceed = false;
         return;
      }

      errCode = VirtCp.VipFluoroGetPrms(ref lp);   
   }

   byteImage = new byte[imageSize];
   try
   {
      if (errCode == (int)HCPError.HCP_NO_ERR)
      {
         logger.WriteLine("Transfering image byte data for processing");

         Marshal.Copy(lp.BufPtr, byteImage, 0, imageSize); // this is the copy function that works 80% of the time, but at random it throws me into a memory access violation

         logger.WriteLine("Saving raw and bmp images");
         bool firstrun = true;
         int BW_timeout = 0;
         while ((ImageProcess_1.IsBusy && ImageProcess_2.IsBusy && ImageProcess_3.IsBusy) || firstrun)
         {
            firstrun = false;
            BW_timeout++;
            if (BW_timeout >= 300000)
            {
               logger.WriteLine("Errors trying to convert images");
               OkProceed = false;
               return;
            }
            if (!ImageProcess_1.IsBusy)
            {
               ImageProcess_1.RunWorkerAsync();
            }
            else if (!ImageProcess_2.IsBusy)
            {
               ImageProcess_2.RunWorkerAsync();
            }
            else if (!ImageProcess_3.IsBusy)
            {
               ImageProcess_3.RunWorkerAsync();
            }
         }

         OkProceed = true;
      }
      else
      {
         logger.WriteLine("Error from detector function call: " + HCPErrorText.GetErrorText(errCode));
         OkProceed = false;
         logger.WriteLine("Will Try to obtain image again");
      }
   }
   catch (Exception ex)
   {
      logger.WriteLine(ex.Message);
      MemoryError = true;
   }

   try
   {
      Marshal.FreeHGlobal(image);    
   }
   catch (Exception ex)
   {
      logger.WriteLine(ex.Message);
   }
}

1 Ответ

0 голосов
/ 03 ноября 2018

Разыменование указателя требует две вещи:

  • Память, на которую указывает указатель, должна быть выделена во время разыменования .
  • Любое обращение к смещению от указателя должно быть меньше размера выделенной памяти.

Поэтому, если вы получаете нарушение прав доступа, есть только три возможности:

  • Указатель никогда не был на действительной памяти вообще. У вас есть указатель мусора.
  • Указатель был на действительную память в прошлом, но теперь не действителен из-за освобождения. Доступ к памяти до освобождения.
  • Смещение, которое вы используете при разыменовании, больше, чем у блока.

В какой из этих трех ситуаций вы находитесь, мы понятия не имеем.

Когда мне приходилось отлаживать такие проблемы в прошлом, я дал указание неуправляемой куче записывать детали распределений и освобождений, чтобы я мог видеть, в какой из этих трех ситуаций я находился. Удачи!

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