2012-07-22 68 views
1

以下代码的一个变体用于工作,但现在我收到内存泄漏,如下面的屏幕截图所示。我将代码从另一个线程移至TimerElapsed事件(请参阅截图中的堆栈跟踪),对MD 3.0.3.4和MT 5.3.4进行了各种代码更新和升级。不幸的是,我似乎无法弄清楚为什么它不再工作。恢复到从普通线程调用的代码的先前版本似乎也不起作用。这是MD或MT当前版本中的错误吗?单触式内存泄漏

正如你所看到的,我使用NSAutoReleasePool以及在最后强制垃圾收集,它仍然不起作用!

编辑:我添加的代码下面,从通过DrawCustomImage其声明痕迹unpackedImage,然后进入SetImages()作为“imageToSet”参数,然后进入窗格在overlayImage()的“覆盖”参数。 SetImage在主线程中调用它内部的代码,因为当它最终调用UpdateLiveScreen(带有最终的overlayedImage)时,它实际上会绘制到屏幕上。

static UIImage unpackedImage = new UIImage(); 

    public static void DrawCustomImage(IntPtr buffer, int width, int height, int bytesPerRow, CGColorSpace colSpace, byte[] rawPixels, ref UIImage unpackedImage) 
    { 
     using (var pool = new NSAutoreleasePool()) 
     { 
      GCHandle pinnedArray = GCHandle.Alloc(rawPixels, GCHandleType.Pinned); 
      IntPtr pointer = pinnedArray.AddrOfPinnedObject(); 

      // Set a grayscale drawing context using the image buffer 
      CGBitmapContext context = new CGBitmapContext(pointer, width, height, 8, bytesPerRow, colSpace, CGImageAlphaInfo.None); 

      try 
      { 
       // Convert the drawing context to an image and set it as the unpacked image 
       //using (var pool = new NSAutoreleasePool()) 
       { 
        using (var img = context.ToImage()) 
        { 
         unpackedImage = UIImage.FromImage(img); 
        } 
       } 
      } finally 
      { 
       pinnedArray.Free(); 
       if (context != null) 
        context.Dispose(); 
      } 
     } 
     GC.Collect(); 
    } 

    SetImages(labelText, symbolArray[0], unpackedImage, points); 

    public static void SetImages(String labelText, UIImage symbol, UIImage imageToSet, PointF[] points) 
    { 
     appReference.InvokeOnMainThread(delegate 
     { 
      int imageWidth = 716; 
      int imageHeight = (int)imageToSet.Size.Height; 
          int nextFreeMainImageColumn = 5; // This gets set dynamically, but is simplified here for readability 

      lock (displayLocker) 
      { 
       // Get the current doppler image 
       UIImage mainImage = GetMainImage(); 

       // Add the new imageToSet to the current image by overlaying it adjacent to the current image 
       UIImage overlayedImage = overlayImage(mainImage, imageToSet, 
            new RectangleF(0, 0, imageWidth, imageHeight), 
            new RectangleF(nextFreeMainImageColumn, 0, imageToSet.Size.Width, imageHeight)); 

       // Update the live screen with the updated image and frame number 
       LiveCont.UpdateLiveScreen(labelText, symbol, overlayedImage, points); 
      } 
     }); 
    } 

    public static UIImage overlayImage(UIImage image, UIImage overlay, RectangleF imageBoundingBox, RectangleF overlayBoundingBox) 
    { 
     int numBytes = 4; // Four bytes per pixel for a color image (Alpha, Red, Green, Blue) 
     int bytesPerRow = (int)imageBoundingBox.Width * numBytes; 

     // Set a color drawing context 
     CGBitmapContext context = new CGBitmapContext(
      IntPtr.Zero, 
      (int)imageBoundingBox.Width, 
      (int)imageBoundingBox.Height, 
      8, 
      bytesPerRow, 
      CGColorSpace.CreateDeviceRGB(), 
      CGImageAlphaInfo.NoneSkipFirst 
     ); 

     UIImage overlayedImage = null; 
     try 
     { 
      context.DrawImage(imageBoundingBox, image.CGImage);    // Draw the main image 
      context.DrawImage(overlayBoundingBox, overlay.CGImage);   // Draw the overlay 

      using (var img = context.ToImage()) 
      { 
       overlayedImage = UIImage.FromImage(img);     // Convert the context back to an image 
      } 
     } 
     finally 
     { 
      if (context != null) 
       context.Dispose(); 
      image.Dispose(); 
     } 

     return overlayedImage; 
    } 

enter image description here

+0

我回到了MT 5.2.12,问题消失了,所以MT 5.2.12和5.3.4之间的MT代码中一定有一些错误。 – nbonwit 2012-07-22 02:22:36

回答

0

由于用于填充bug report

当您拨打电话ToImage(请参阅source)时,本机会拨打CGBitmapContextCreateImage(来自仪器的堆栈跟踪)。该代码在5.2.12和5.3之间没有改变,所以它可能不是罪魁祸首。

管理GCImage不采取额外的关于手柄(true在.ctor使用)(见source,近期没有任何变化)。

所以这需要我们从您的方法返回的unpackedImageUIImage。在此调用周围使用自动 有一个变化(在5.3.x中)。

否则,在/你如何处理返回的unpackedImage结束(和哪个线程,例如CoreGraphics中是线程安全的,而UIKit的大多是不是)。

您可以添加显示此代码(在这里或私人的bug报告)吗?我不认为问题出现在你的代码中(因为它在5.2.x上工作),但它会使跟踪更容易。

请注意,调用GC.Collect是没有帮助的(和它很少是),因为情况下,您正在使用的所有执行IDisposable(其中一般立即资源的部署和取出完成步骤),并手动或处置这些using