内存泄漏/崩溃转换图像数据

时间:2012-10-19 23:23:17

标签: crash xamarin.ios garbage-collection uiimage nsdata

以下代码在~200次调用后崩溃。我在每次调用后尝试使用GC,并使用另一个GC尝试使用MemoryWarning块,但它仍然崩溃。

public byte[] ConvertImage(string base64String)
{
    try
    {
        byte[] encodedDataAsBytes = Convert.FromBase64String ( base64String );
        base64String = "";
        NSData data = UIImage.LoadFromData ( NSData.FromArray ( encodedDataAsBytes ) ).AsPNG();
        encodedDataAsBytes = null;
        Byte[] returnBytes2 = new Byte[data.Length];
        System.Runtime.InteropServices.Marshal.Copy
        (data.Bytes, returnBytes2, 0, System.Convert.ToInt32(data.Length));
        data.Dispose();
        return returnBytes2;
    }
    catch(Exception ex)
    {
        Log.LogError("ConvertImage", ex);
        return null;
    }
}

TIA, 瑞克

经过Xamarin支持的大量帮助和极好的帮助 - 答案是将方法包装在using (var pool = new NSAutoreleasePool ())

一切都很好!哦,另外一点,将.PNG改为.JPEG也减轻了负担。

1 个答案:

答案 0 :(得分:3)

这是非常耗费内存的。 base64 stringbyte[]数组,NSDataUIImage,第二个NSData,第二个byte[]数组。这是您正在处理的图像所需内存的很多倍。

根据代码的调用方式(例如,对一堆图像进行循环),您可能比GC能够回收它更快地分配内存。在某些时候,iOS会触发一个内存警告(但这对循环没有帮助),如果内存使用率没有迅速降低,它会杀死你。

您可以通过处理代码创建的每个IDisposable实例来轻松降低内存需求。现在,您只处置了您创建的两个NSData个实例中的一个,并且您没有处置UIImage。你可以这样处理所有这些:

byte[] encodedDataAsBytes = Convert.FromBase64String ( base64String );
using (var nsd1 = NSData.FromArray ( encodedDataAsBytes ))
using (var img = UIImage.LoadFromData ( nsd1 ))
using (NSData data = img.AsPNG ()) {
    byte[] returnBytes2 = new byte [data.Length];
    Marshal.Copy (data.Bytes, returnBytes2, 0, (int) data.Length);
    return returnBytes2;
}

接下来,代码的目的是什么?即你在使用包含PNG图像的byte[]做什么?它本身并不是很有用,但是如果你只是将它保存到磁盘上,那么你可以从NSData执行此操作并跳过上一次byte[]分配。

也可以应用依赖于使用的其他技巧(例如,在可能的情况下重用第二个byte[]缓冲区)但我们需要了解有关代码使用方式的更多信息。