元帅。复制尝试在随机时间读取或写入受保护的内存

时间:2018-11-02 20:10:30

标签: c# .net visual-studio visual-studio-2017

我的代码有问题,它可以正常工作, 但是在随机时间调用Marshal.Copy函数会使我获得访问冲突异常。 我的程序从X射线扫描仪获取图片。 X射线扫描仪将图像存储在内存中,并为我提供了从中获取该图片的指针。 我使用Marsharl.Copy将指针中的信息放入大小为2 * Width(x个像素的个数)* height(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 :(得分:2)

取消引用指针需要两件事:

  • 指针引用的内存必须在取消引用时分配
  • 任何对指针偏移的取消引用都必须小于所分配内存的大小。

因此,如果遇到访问冲突,则只有三种可能性:

  • 指针根本没有指向有效内存。您有一个垃圾指针。
  • 该指针过去曾指向有效内存,但由于释放而现在不再有效。在释放之前,访问内存
  • 取消引用中使用的偏移量大于块。

您处于这三种情况中的哪一种,我们不知道。

过去,当我不得不调试此类问题时,我对非托管堆进行了插桩,以记录分配和释放的详细信息,这样我就可以看到我处于这三种情况中的哪一种。祝你好运!