问题描述
我的 iPad 应用程序是在 MonoTouch 中开发的,因为我想避免所有内存管理地狱,但似乎并非如此.在模拟器上一切正常,但是当我在设备上测试我的应用程序时,我惊恐地发现它在一些内存警告后很快被操作系统杀死.我的应用程序是一个简单的图像浏览器,它加载一些 PNG 图像并使用 UIScrollView 中的一些 UIViews 显示它们,在触摸时加载下一个或上一个.在模拟器上它工作正常.但是在设备上加载和卸载大约 6-11 个图像后,它开始收到内存警告,然后突然该进程被终止.我已经检查了所有实例化周期,并且在加载新图像之前正确删除了所有引用.
My iPad app is developed in MonoTouch, because I wanted to avoid all the memory management hell, but it doesn't seem the case. On the simulator everything works fine, but when I tested my app on the device I discovered with horror that it is quickly killed by the OS after some memory warnings.My app is a simple image browser, it loads some PNG images and shows them using some UIViews inside an UIScrollView, loading the next or the previous when getting a touch. On the simulator it works fine. But on the device after loading and unloading about 6-11 images it start getting memory warnings and then suddenly the process is killed. I've checked all my instancing cycles, and I correctly delete all references before loading new images.
所以我启动了 Instruments 并开始分析我的应用程序在 iPad 上的内存分配.在那里我发现 Live 字节只有大约 5-9 MB,这正是我所期望的,但是由于某种奇怪的原因,几乎没有收集死内存分配,因为在分配了大约 50 MB(少于 5-9 MB 的它是 Live Bytes)它正在被杀死!这是我的应用程序的 Instruments 分析会话的屏幕截图:
So I started Instruments and began profiling the memory allocation of my App on the iPad. There I discovered that the Live bytes are only around 5-9 MB, just what I expected, but for some strange reason the dead memory allocations are almost not collected at all, because after allocating about 50 MB (less than 5-9 MB of it being Live Bytes) it is being killed! Here is a screenshot of the Instruments profiling session of my App:
这是heapshots序列:
And here is the heapshots sequence:
也有一些小的泄漏,但我认为它们还不足以成为罪魁祸首.它们都是 strdup 的 48 字节泄漏,这是在 iOS 5.1 中发布 UIScrollView 时的一个已知问题:
There are also some small leaks, but I think that they are not big enough to be the culprits. They are all 48 bytes leaks from strdup, a known issue when releasing UIScrollView in iOS 5.1:
即使一切看起来都不错并且分配的 Live Bytes 仍为 5 MB,我的应用程序的实际内存呈指数增长,然后在 iPad 上被杀死高达 50 MB,在 iPhone4S 上高达 314 MB,据报道内存监视器:
Even with everything that seems ok and the Live Bytes allocated are still at 5 MB, the REAL memory of my app grows exponentially before being killed up to 50MB on iPad, and up to 314 MB on the iPhone4S, as reported by the Memory Monitor:
有人可以告诉我是否有一种方法或实用程序可以发现问题所在?这是单触式垃圾收集器的错误吗?还是有一些我没有正确处理的对象?以及如何使用分析器找到那些?我已经检查了两天的代码,但似乎一切正常.
Does somebody can tell me if there is a method, or an utility to discover what and where the problem is? Is it a bug of the monotouch garbage collector? Or are there some object I don't dispose correctly of? And how I can find those with the profiler? I've checked my code for two days, but everything seems right.
这是我的加载/实例化/处理周期代码:
Here is my code for the loading/instancing/disposing cycle:
void StartImageLoadingThread()
{
tokenSource = new CancellationTokenSource ();
token = tokenSource.Token;
Task task1 = new Task( () => PerformLoadImageTask(token),token);
task1.Start();
}
void PerformLoadImageTask(CancellationToken token)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Task {0}: Cancelling", Task.CurrentId);
return;
}
current_uiimage_A = UIImage.FromFileUncached(file_name);
page_A_image_view.Image = current_uiimage_A;
}
void UnloadImageAFromMemory()
{
page_A_image_view.Image = null;
current_uiimage_A.Dispose();
current_uiimage_A = null;
}
是否有一种方法可以捕获未正确处理的对象?Instruments 报告活动字节很低,泄漏几乎为零,那么为什么不处理死对象?即使我的应用程序几分钟内没有发生任何事情,GC 似乎也没有完成他的工作,即使我在我的代码中明确地调用它.我什至尝试了新的实验性垃圾收集器,但它更糟,更快地杀死我的应用程序.
Is there a method to catch an object that is not been disposed correctly? Instruments reports that the live bytes are low, leaks are almost zero, then why the dead objects are not disposed of? Even if nothing happens in my app for minutes, the GC doesn't seem to make his job, even if I call it explicity in my code. I even tried the new experimental Garbage Collector, but it is even worse and quicker to make my app killed.
我在 Xamarin 网站上找不到任何指南或分步指南,用于对内存警告进行故障排除或跟踪错误的分配.
I cannot find any guideline or step-by-step guide on the Xamarin website for troubleshooting memory warnings or tracking down bad allocations.
非常感谢任何帮助或建议,谢谢!
Any help or suggestion is very appreciated,Thanks!
更新:我已经减小了一些图像和 uiviews 的大小和分辨率,Live Bytes 现在从 9 MB 降到了 5 MB,但无论如何在出现一些内存警告后应用程序仍然被杀死.
UPDATE:I've reduced the size and the resolution of some images and uiviews, and the Live Bytes are now dropped from 9 MB to 5 MB top, but the app is still killed after some memory warnings no matter what.
更新2:正如 Javier 所建议的,我已经删除了后台任务并直接进行了调用,内存泄漏消失了!似乎 MonoTouch 垃圾收集器有一个错误,当 UIImages 在不同的线程中分配和处置时,它无法收集内存.但是现在当我滚动时我的应用程序非常无响应,所以我需要找到一个解决方案来在不同的线程中完成它!但是如何?
UPDATE 2:As suggested by Javier I've removed the background tasks and made the calls directly and the memory leak is gone! It seems that the MonoTouch garbage collector have a bug and is unable to collect memory when UIImages are allocated and disposed in a different thread. But now my app is awfully unresponsive when I scroll, so I need to find a solution to do it in a different thread! But how?
推荐答案
我在使用 UIImage.FromFile
时遇到了问题.我的应用程序正在使用一个任务加载大量 png 图片,并将其显示在主线程中.
I had problems with UIImage.FromFile
. My app is loading a lot of png images using a task, and showing it in the main thread.
我在后台任务中添加了一个GC.Collect
,但它并没有解决问题.我不得不删除后台任务,在主线程中完成所有工作并调用 GC.Collect
.似乎 Image.Dispose 没有释放图像内存:(
I added a GC.Collect
in the background task, but it hasn't fixed the problem. I had to remove the background task, do all the stuff in the main thread AND call GC.Collect
. It seems that Image.Dispose is not releasing the image memory :(
但是当你有另一个任务时它不起作用,所以我不得不删除它:(
But it doesn't work when you have another task, so i had to remove it :(
是的,它不起作用......
Yes it is not working....
这篇关于MonoTouch:应用程序因内存不足而被杀死,为什么?实时字节分配 5 MB top的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!