0

在我得到答案后编辑:
- 实际上没有内存泄漏。添加到 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) 
4

1 回答 1

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{

}

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

于 2012-03-06T16:35:06.400 回答