【发布时间】: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