0

我得到了答案後編輯:
- 實際上沒有內存泄漏。添加到NSInvocationOperation的對象將被保留並按預期發佈。
保留參數完成NSIvocationOperation後?

爲什麼我對以後的對象添加到NSInvocationOperation它被保留,也該操作結束它保留再次?

我該如何防止內存泄漏?

下面是我的示例代碼。 我很抱歉,如果那麼多代碼讓你煩惱,但我只是想確保我沒有錯過任何東西。 此外,NSLogs旁邊的註釋顯示它們的輸出。

我的整個AppDelegate.m:

// 
// AppDelegate.m 
// BRISI 
// 
// Created by Aleksa Topic on 2/22/12. 
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. 
// 

#import "AppDelegate.h" 

@implementation AppDelegate 

@synthesize window = _window; 

- (void)dealloc 
{ 
    [_window release]; 
    [super dealloc]; 
} 

- (BOOL)application:(UIApplication *)application 
     didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    NSObject *a = [[NSObject alloc] init]; 
    NSLog(@"a1: %d", a.retainCount); // a1: 1 

    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] 
             initWithTarget:self 
              selector:@selector(s:) 
               object:a]; 
    NSLog(@"a2: %d", a.retainCount); // a2: 2 

    [a release]; 
    NSLog(@"a3: %d", a.retainCount); // a3: 1 

    [operationQueue addOperation:operation]; 
    [operation release]; 
    NSLog(@"a4: %d", a.retainCount); // a4: 1 

    NSLog(@"oper1: %@", operation); // oper1: <NSInvocationOperation: 0x6a3f7d0> 

    NSLog(@"a5: %d", a.retainCount); // a5: 1 
    NSLog(@"a5: %d", a.retainCount); // a5: 1 
    NSLog(@"a5: %d", a.retainCount); // a5: 1 
    NSLog(@"a5: %d", a.retainCount); // a5: 2 
    NSLog(@"a5: %d", a.retainCount); // a5: 2 
    NSLog(@"a5: %d", a.retainCount); // a5: 2 
    NSLog(@"a5: %d", a.retainCount); // a5: 2 
    NSLog(@"a5: %d", a.retainCount); // a5: 2 

    // And here I get: "Thread 1: Program received signal: "EXC_BADACCESS"." 
    NSLog(@"oper2: %@", operation); 

    self.window = [[[UIWindow alloc] 
        initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 
    // Override point for customization after application launch. 
    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

- (void)s:(NSArray *)a 
{ 
    NSLog(@"a (s:): %d", a.retainCount); // a (s:): 1 
    NSLog(@"a (s:): %d", a.retainCount); // a (s:): 1 
    NSLog(@"a (s:): %d", a.retainCount); // a (s:): 1 
} 

@end 

這裏是在輸出的情況下要比較:

GDB is free software, covered by the GNU General Public License, and you are 
welcome to change it and/or distribute copies of it under certain conditions. 
Type "show copying" to see the conditions. 
There is absolutely no warranty for GDB. Type "show warranty" for details. 
This GDB was configured as "x86_64-apple-darwin".sharedlibrary apply-load-rules all 
Attaching to process 7927. 
2012-03-06 16:19:20.712 BRISI[7927:207] a1: 1 
2012-03-06 16:19:20.715 BRISI[7927:207] a2: 2 
2012-03-06 16:19:20.715 BRISI[7927:207] a3: 1 
2012-03-06 16:19:20.716 BRISI[7927:207] a4: 1 
2012-03-06 16:19:20.717 BRISI[7927:207] oper1: <NSInvocationOperation: 0x6858da0> 
2012-03-06 16:19:20.717 BRISI[7927:1e03] a (s:): 1 
2012-03-06 16:19:20.717 BRISI[7927:207] a5: 1 
2012-03-06 16:19:20.718 BRISI[7927:1e03] a (s:): 1 
2012-03-06 16:19:20.718 BRISI[7927:207] a5: 1 
2012-03-06 16:19:20.718 BRISI[7927:1e03] a (s:): 1 
2012-03-06 16:19:20.719 BRISI[7927:207] a5: 1 
2012-03-06 16:19:20.719 BRISI[7927:207] a5: 2 
2012-03-06 16:19:20.720 BRISI[7927:207] a5: 2 
2012-03-06 16:19:20.720 BRISI[7927:207] a5: 2 
2012-03-06 16:19:20.721 BRISI[7927:207] a5: 2 
2012-03-06 16:19:20.721 BRISI[7927:207] a5: 2 
Current language: auto; currently objective-c 
(gdb) 
+2

只是子類'NSObject',重寫它的'dealloc'把NSLog()'放在那裏,並用它作爲'NSInvocationOperation'的對象。這將幫助你放心,實際上'a'會被釋放。不要擔心保留數量 - 他們可能會瘋狂地飆升,所以他們不會告訴你任何事情。 – Costique 2012-03-06 15:46:08

+0

@Costique但是它的'dealloc'永遠不會被調用(因爲如果調用'dealloc',那麼這個對象就消失了,對吧?)。你可以從例子中看到它,因爲'a.retainCount'沒有崩潰的應用程序。 – Aleksa 2012-03-06 16:10:34

+0

無論如何都會調用它,因爲您發佈的代碼中沒有任何泄漏。當操作被釋放時,調用對象可能已經被添加到自動釋放池中,這會延遲其釋放。請注意,'NSInvocationOperation'創建一個保留該對象的'NSInvocation'。這可能解釋你從哪裏獲得'retainCount == 2'。 – Costique 2012-03-06 16:15:27

回答

0

每當我處理一個棘手的保留業務我做的/釋放套當然我會覆蓋適當的方法:

@interface RetainCountChecker : NSObject 

@end 

@implementation RetainCountChecker 

-(oneway void)release{ 
    [super release]; 
    NSLog(@"release - retainCount = %d", [self retainCount]); 
} 

-(id)retain{ 
    id result = [super retain]; 

    NSLog(@"retain - retainCount = %d", [self retainCount]); 
    return result; 
} 

-(void)dealloc{ 
    [super dealloc]; 
} 

@end 

將斷點放入保留,釋放,並且dealloc方法允許您查看每個被調用的時間和方式。 在你的情況下,NSInvocationOperation會自動釋放內部的NSInvocation對象。包裹有問題的代碼在

@autorelease{ 

} 

塊將dealloc中的 「a」 之前-application:didFinishLaunchingWithOptions:方法中返回。

+0

它實際上被釋放。混淆是'NSInvocationOperation'被釋放,我的對象不會立即被釋放。 – Aleksa 2012-03-07 10:15:00