【问题标题】:Arguments retained After finishing NSIvocationOperation?完成 NSIvocationOperation 后保留的参数?
【发布时间】:2012-03-06 15:36:53
【问题描述】:

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

为什么在我将一个对象添加到 NSInvocationOperation 之后它会被保留,并且该操作完成之后它又会再次保留

以及如何防止内存泄漏?

下面是我的示例代码。 如果这么多代码让您烦恼,我深表歉意,但我只是想确保我没有遗漏任何东西。 此外,NSLogs 旁边的 cmets 会显示它们的输出。

我的整个 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) 

【问题讨论】:

  • 只是子类NSObject,覆盖它的dealloc 以将NSLog() 放在那里并将其用作NSInvocationOperation 的对象。这将帮助您放心,a 确实会被释放。并且不要担心保留计数 - 它们可能会像疯了一样飙升,所以它们不会告诉你任何事情。
  • @Costique 但它的dealloc 永远不会被调用(因为如果dealloc 被调用,那么对象就消失了,对吧?)。您可以从示例中看到它,因为 a.retainCount 不会导致应用程序崩溃。
  • 无论如何都会调用它,因为您发布的代码中没有泄漏。当操作被释放时,调用对象可能已被添加到自动释放池中,这将延迟其释放。请注意,NSInvocationOperation 创建了一个保留对象的NSInvocation。这可以解释你从哪里得到retainCount == 2
  • @Costique 我已将 NSLog 放入 dealloc,它实际上已发布。谢谢。

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


【解决方案1】:

每当我处理棘手的保留/释放操作集时,我都会确保我覆盖了适当的方法:

@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”。

【讨论】:

  • 它实际上被释放了。困惑在于NSInvocationOperation 被释放,而我的对象没有立即被释放。
猜你喜欢
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
  • 2013-01-22
  • 2017-12-30
  • 1970-01-01
相关资源
最近更新 更多