【问题标题】:How do I prevent a memory leak with UIImage.FromImage(context.ToImage())?如何使用 UIImage.FromImage(context.ToImage()) 防止内存泄漏?
【发布时间】:2012-05-23 03:11:28
【问题描述】:

我有以下函数将像素的字节数组转换为图像。但是,我的行中有内存泄漏:

unpackedImage = UIImage.FromImage(context.ToImage());

当我注释掉上面的行时,泄漏就消失了。泄漏非常严重,iOS 在启动后大约 30 秒内杀死了我的应用程序。就是因为这行代码。

如何防止这种内存泄漏?有没有更好的方法来做我想做的事情?

    public static void DrawCustomImage2(IntPtr buffer, int width, int height, int bytesPerRow, CGColorSpace colSpace, byte[] rawPixels, ref UIImage unpackedImage)
    {
        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);

        // Turning off interpolation and Antialiasing is supposed to speed things up
        context.InterpolationQuality = CGInterpolationQuality.None;
        context.SetAllowsAntialiasing(false);

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

这是分析屏幕截图(当关键代码行被注释掉时,选中的项目都会消失)。您可以看到检查的项目(尤其是 Malloc)如何随着时间的推移而增长。

这是 Malloc 1.50KB 的放大视图。您可以在右侧的扩展详细信息窗格中看到它正在调用 CGBitmapContextCreateImage 和 CGDataProviderCreateWithCopyOfData,然后是 malloc。

这是带有 Rolf 建议的分析屏幕截图。我运行了两次图像循环。你可以看到它在第一个循环结束时清理了额外的内存,但是系统第二次清理的速度不够快,iOS 杀死了我的应用程序(你可以在右上角看到内存不足警告标志角落)。

【问题讨论】:

    标签: c# xamarin.ios uiimage byte pixels


    【解决方案1】:

    这样做:

    using (var pool = new NSAutoreleasePool ()) {
        using (var img = context.ToImage ()) {
            unpackedImage = UIImage.FromImage (img); 
        }
    }
    

    【讨论】:

    • 你的建议有点奏效......你可以从上面的截图中看到它在我的循环结束时清理了内存,但这对于第二个循环来说还不够好,iOS 被杀应用程序。如何让它清理循环内各个点的内存?
    • 我在 finally 块中放置了一个手动 GC.Collect() ,现在一切似乎都运行良好!非常感谢您的快速帮助!!有没有比显式调用 GC.Collect() 更好的方法来解决这个问题?
    猜你喜欢
    • 2019-10-17
    • 2010-12-20
    • 2021-10-22
    • 2010-09-21
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    相关资源
    最近更新 更多