2011-09-20 217 views
1

Screen shot of memory leak in instruments根據儀器iOS內存泄漏

請幫忙!我已經閱讀了內存管理規則,但也許我在某處指向他們。儀器告訴我,我有以下代碼泄漏:

NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil]; 
NSArray *objects 
    = [NSArray arrayWithObjects:sPlateToAdd, [ 
     [[NSNumber alloc] initWithInt:1] autorelease], 
     [[[NSNumber alloc] initWithInt:1] autorelease], 
     nil]; 

NSMutableDictionary *dPlateToAdd 
    = [NSMutableDictionary dictionaryWithObjects:objects forKeys:keys]; // 93.4%   
[self.aFinals addObject:dPlateToAdd]; // 6.6% 

鑰匙和對象數組不被alloc'ed或init'ed,所以我不認爲我需要釋放那些?

然後對象內部的數字被自動釋放,所以他們確定不是他們? 而sPlateToAdd是一個傳入此代碼所在方法的字符串,所以我不是它的所有者,所以我不需要釋放它。還是我?我不得不在某個地方做錯事。

的應用程序運行在iPad上完全沒問題,但狗在iPhone 3GS的慢,我希望修復這個內存泄漏可能會加速它的一點點...

這是創建自我的方法.aFinals,從文本輸入中傳遞一個字符串。我ommitted一些行,但self.aFinals無法與他們進行互動

-(id)initWithTerm:(NSString *)thisTerm { 
    ... 
    ... 
    self.aFinals = [[NSMutableArray alloc] init]; 

    return self; 
} 

然後,我有大約5嵌套循環,該呼叫addPlateToFinals在所有環路的中間的3倍,創造thisPlate ,這成爲sPlateToAdd

// replace 1st occurance 
NSString *thisPlate = [thisBase 
    stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat: 
     @"(^[^%@]+)%@(.*$)", 
     thisChar, 
     thisChar] 
    withString:[NSString stringWithFormat:@"$1%@$2", thisSub] 
    ]; 

    [self addPlateToFinals:thisPlate withSubCount:thisSubCount]; 
// replace 2nd occurance 
thisPlate = [thisBase 
    stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat: 
     @"(^[^%@]+%@.*)%@",  
     thisChar, 
     thisChar, 
     thisChar] 
    withString:[NSString stringWithFormat:@"$1", thisSub] 
    ]; 

// then it does it again, with slightly different regex 

這是泄漏是來自完整的方法:

-(void)addPlateToFinals:(NSString *)sPlateToAdd withSubCount:(NSNumber *)nSubCount { 
// plate must be less than 7 characters and great than 2 chars 
if (
    [sPlateToAdd length] <= [self.nPlateMax intValue] && 
    [sPlateToAdd length] >= [self.nPlateMin intValue] 
    ) {  

    NSMutableArray *aSearchFinals = [self arrayOfFinals]; 

    // add plate if it is not already in the finals array 
    if(![aSearchFinals containsObject:sPlateToAdd]) { 

     // filter out results that cannot be converted to valid plates 
     NSPredicate *potential = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{0,3}[0-9]{1,3}[a-z]{0,3}$'"]; 
     NSPredicate *impossible1 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{2}[0-9]{2,3}[a-z]{2}$'"]; 
     NSPredicate *impossible2 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z][0-9]{3}$'"]; 
     NSPredicate *impossible3 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{2}[0-9]{2}$'"]; 
     NSPredicate *impossible4 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[0-9]{2}[a-z]{2}$'"]; 

     if(
      [potential evaluateWithObject: sPlateToAdd] && 
      ![impossible1 evaluateWithObject: sPlateToAdd] && 
      ![impossible2 evaluateWithObject: sPlateToAdd] && 
      ![impossible3 evaluateWithObject: sPlateToAdd] && 
      ![impossible4 evaluateWithObject: sPlateToAdd] 
     ){     

      NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil]; 
      NSArray *objects = [NSArray arrayWithObjects: 
            sPlateToAdd, 
            [[[NSNumber alloc] initWithInt:1] autorelease], 
            [[[NSNumber alloc] initWithInt:1] autorelease], 
            nil 
           ]; 

      NSDictionary *dPlateToAdd = [NSDictionary dictionaryWithObjects:objects forKeys:keys];   
      [self.aFinals addObject:dPlateToAdd]; 
     } 
    } 
} 

}

+0

什麼樣的對象被泄露? – mja

+0

也許,skeater意味着分配 –

+0

_NSCFDictionary –

回答

3

你應該表現出整個`addPlateToFinals'的方法,sPlateToAdd可能發生泄漏。

基於新添加的代碼self.aFinals如果屬性聲明爲retain(並且我是%99),則發生泄漏。應該是:

self.aFinals = [[[NSMutableArray alloc] init] autorelease]

甚至更​​好:

self.aFinals = [NSMutableArray array]

+0

好的,但不要恨我,如果我的代碼是可怕的...我正在從網站開發轉換。我會附上它的問題。 –

+0

我是誰來判斷?:) –

+0

那麼你的聲望比我的高呢!我已經添加了方法 –

0

您應該使用NSDictonary代替NSMutableDictonary如果有可能,因爲對象的可變的版本會比不變更多的內存。另外,我也做了一些化妝品的增強功能代碼

NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil]; 
NSArray *objects = [NSArray arrayWithObjects:sPlateToAdd, 
        [NSNumber numberWithInt:1], 
        [NSNumber numberWithInt:1], 
        nil]; 

NSDictonary *dPlateToAdd = [NSDictonary dictionaryWithObjects:objects forKeys:keys]; // 93.4%   
[self.aFinals addObject:dPlateToAdd]; // 6.6% 
+0

那會消除內存泄漏嗎? 'NSNumber numberWithInt:1'與我寫的內容完全相同嗎?感謝您的快速回復 –

+0

您提供的代碼中沒有內存泄漏。我們可能談論分配或時間分析? –

+0

NSNumber numberWithInt:1 - 你是對的,它只是更具可讀性 –

0

你可能有此對象的內存泄漏沒有這個代碼負責的。

Cocoa/Cocoa Touch環境中的內存泄漏發生在對象保留時間超過其釋放時間。這些工具將指出它的分配位置,而不是漏出的位置,因爲這些工具無法確定哪個保留缺少一個發佈。他們只是保留和發佈;沒有什麼東西將它們聯繫在一起,但是公約。

首先,做一個Build &分析。這可能會指出你的代碼在做什麼不當導致泄漏。嚴肅對待分析器警告,特別是如果它們與內存管理有關。

如果建立&分析不能解決你的問題,通過您的應用程序再次剖析和研究泄漏塊的歷史。這將顯示你每次塊被保留或釋放。查找沒有相應版本或autorelease的保留。 (你實際上可能會發現很容易簡單地通過您的代碼閱讀,尋找不平衡保留,不用工具。)

+0

謝謝,分析器沒有給我任何關於我的代碼的警告,它只是提到了我正在使用的第三方插件中的一些不推薦使用的代碼。當我將它傳遞給方法時,我保留了一個變量嗎? –

+0

除非該方法明確保留它。但是,如果該方法將其傳遞給其他某個東西,它會將其傳遞給其他東西,而這恰好會保留它,而不會在稍後釋放它......內存泄漏。它可以真的是一場狩獵。這就是爲什麼塊歷史如此有用。 –