【问题标题】:iPhone memory crash: signal 0iPhone内存崩溃:信号0
【发布时间】:2011-07-21 22:36:53
【问题描述】:

我正在开发一个 iPhone 应用程序,它显示地图上的一些图块。我有一个从互联网或文件系统加载磁贴的线程。这是一个没完没了的线程

while( true ){ //get tile into cache }

不幸的是,在显示很多图块后,应用程序以信号 0 崩溃,这意味着我的内存不足..

我的想法是,在这个无穷无尽的线程中,瓷砖被加载为自动释放,并且不会自动释放..

基本上我在我无尽的线程中这样做:

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
while( true ){
    UIImage * img = nil;
    NSFileHandle * tile = [NSFileHandle fileHandleForReadingAtPath:filePath];
    if( tile ){
        NSData * data = [tile readDataToEndOfFile];
        if( data ){
            img = [[UIImage alloc] initWithData:data];
            local = YES;
        }
    }
    if( img == nil ){
        NSURL * url = [NSURL URLWithString: [NSString stringWithFormat:@"http://tile.openstreetmap.org/%@.png", todoKey ] ];
        img = [[UIImage alloc] initWithData: [NSData dataWithContentsOfURL: url options:NSDataReadingMapped error:&error] ];
    }

    if( img != nil ){
        [cache addObject:img]; //cache is an array of tiles
    }

    [img release];
    [self cleanupCache]; //method to check if cache is full, and if so remove's objects from it
}
[pool release];

我认为自动释放池不会不时清理“死”引用,并且所有图块都保存在内存中。当我检查仪器泄漏时,没有任何内存泄漏,但“实时内存”不断增加..

知道为什么会发生这种情况以及如何防止它吗?

【问题讨论】:

  • 为什么需要无限循环?
  • 在这个循环中,我正在按需下载切片,如果我的视图问:“你有这些切片吗?”线程负责下载它们并将它们放入缓存中。跨度>

标签: iphone memory crash


【解决方案1】:
if( img != nil ){
 [cache addObject:img];

cache 仍然持有您添加的所有对象的引用。您可能应该删除您不会使用的对象。

【讨论】:

  • 感谢 Praveen,但我已经处理好了,抱歉没有说出来。每次下载操作后,我都会检查我的缓存是否已满(x 个对象)。如果是,我会清理缓存并调用 [cache removeObjectAtIndex:i] 将其删除。
  • 好的,你的变量瓷砖怎么样?
  • 它是一个自动释放的对象:NSFileHandle * tile = [NSFileHandle gileHandleForReadingAtPath:filePath];
【解决方案2】:

我修正了您代码中的缩进,希望我做对了。改进后的缩进让一个问题变得显而易见:

你正在释放一个已经释放的对象,你的池。

尝试在循环内移动NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

但很可能你应该首先摆脱循环。

另一个问题是您没有将 img 设置为 nil。如果在循环的第一次运行中存在有效的img,代码将认为它对随后的所有其他循环运行都有效。如果您从缓存中的某处删除 img(并且 img 指向的对象被解除分配),则当您尝试将其添加到缓存中时,您会向解除分配的对象发送保留。

在循环开头添加img = nil;

【讨论】:

  • 嗨,谢谢你修复它.. 但有一件事出了问题.. [pool release] 发生在 while(true) 循环之外(实际上从来没有)......你说我有摆脱循环,但这个线程的意思是按需下载瓷砖,如果我的观点问:“你有这些瓷砖吗?”线程负责下载它们并将它们放入缓存中。还有在我的循环之上,在while(true)之后,我把UIImage * img = nil;,所以这个图像只在循环中..但它仍然不能解决我的问题..
【解决方案3】:

你应该交换程序的前两行:

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
while( true ){
  ...
  [pool release];
}

应该是

while( true ){
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  ...
  [pool release];
}

目前,在第一次循环之后,您创建的 NSAutoreleasePool 将被释放。在此之后,所有自动释放的对象将被添加到调用堆栈中更高的不同 NSAutoreleasePool 中。我怀疑这个父自动释放池在你的程序运行时永远不会释放。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 2011-05-30
  • 2014-08-29
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
相关资源
最近更新 更多