保留参数完成NSIvocationOperation后?

时间:2012-03-06 15:36:54

标签: objective-c multithreading nsoperationqueue reference-counting nsinvocationoperation

得到答案后编辑:
  - 实际上没有内存泄漏。添加到NSInvocationOperation的对象将保留并按预期释放。

为什么在我向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) 

1 个答案:

答案 0 :(得分: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

在retain,release和dealloc方法中放置断点可以让您查看每个方法的调用时间和方式。 在您的情况下,NSInvocationOperation是自动释放内部NSInvocation对象。在

中包装有问题的代码
@autorelease{

}

block将在-application:didFinishLaunchingWithOptions:方法返回之前释放“a”。