2011-03-24 61 views
1

我正在開發一個iPhone應用程序,它顯示地圖上的一些圖塊。我有一個從互聯網或文件系統加載磁貼的線程。這是一個永無止境的線程iPhone內存崩潰:信號0

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

Unfortunateley顯示多少瓷磚信號0,這意味着IM出內存的應用chrashes後..

我的想法是,在這無盡的線程的瓦片被加載自動釋放,並自動釋放NOG ..

基本上即時通訊在我無盡的線程這樣:

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]; 

林以爲autoreleasep ool不時清理「死」的參考,並且所有的瓷磚都保存在內存中。當我檢查與儀器泄漏沒有任何內存泄漏,但'活內存'不斷加起來..

任何想法的原因是爲什麼發生這種情況,我怎麼能防止它?

+0

爲什麼你需要一個無限循環? – MCannon 2011-03-24 08:15:17

+0

在這個循環中,我正在按需下載瓷磚,如果我的觀點問:'你有這些瓷磚嗎?「線程負責下載它們並將它們放入緩存。 – Nick 2011-03-24 09:17:17

回答

2

你應該換第2行方案:

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

應該

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

目前,通過您的循環中的第一次之後,您已經創建了NSAutoreleasePool將被釋放。在此之後,所有自動釋放的對象將被添加到調用堆棧中較高級的不同NSAutoreleasePool。我懷疑當你的程序運行時,這個父autorelease池永遠不會被釋放。

+0

感謝您的答案,把在while循環池大大提高了內存使用率,但還有另一個罪魁禍首:NSURLCache ..我在這裏找到了解決方案: http://www.iphonedevsdk.com/forum/iphone-sdk-development/52972-cfdata-memory -problem.html – Nick 2011-03-24 09:48:01

0
if(img != nil){ 
[cache addObject:img]; 

cache仍然擁有您添加的所有對象的引用。你可能應該刪除你不會使用的對象。

+0

謝謝Praveen,但我已經如果是這樣,我清理緩存並調用[cache removeObjectAtIndex:i]將其刪除。 – Nick 2011-03-24 08:19:53

+0

好的你的可變瓦片怎麼樣? – 2011-03-24 08:29:12

+0

它是一個自動釋放對象: NSFileHandle * tile = [NSFileHandle gileHandleForReadingAtPath:filePath]; – Nick 2011-03-24 08:34:02

0

我在你的代碼中修改了縮進,我希望我的理解正確。改進的凹痕使得一個問題變得明顯:

您正在發佈一個已經發布的對象,即您的池。

嘗試在循環內移動NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

但最有可能的是,你應該擺脫循環擺在首位。

另一個問題是你不設置img爲零。如果在循環的第一次運行中有一個有效的img,那麼代碼會認爲它對於後面的所有其他循環運行都是有效的。如果您從緩存中刪除某處的img(並且img指向的對象將被釋放),則當您嘗試將其添加到緩存時,將保留髮送到釋放對象。

在循環的開始處添加img = nil;

+0

Hiya,感謝您修復它..但有一件事出了問題.. [游泳池釋放]發生在(真正的)循環之外(實際上從未)... 你說我必須擺脫循環,但這個線程的含義是按需下載磁貼,如果我的觀點問:'你有這些磁貼嗎?「線程負責下載它們並將它們放入緩存中。 此外,我的循環,之後(真),我把UIImage * IMG = NIL;所以這個圖像只在循環..但仍然不能解決我的問題.. – Nick 2011-03-24 08:22:16