arrayWithContentsOfFile:导致崩溃
我正在创建一个应用程序,但收到 EXC_BAD_ACCESS 错误。
代码
@interface DNProjectsCategory : DNCategory {
NSArray *projects;
}
@property(nonatomic, retain) NSArray *projects;
@end
和:
@implementation DNProjectsCategory
@synthesize projects;
// MEM
- (void)dealloc {
[projects release];
[super dealloc];
}
// INIT.
- (id)init {
if (self = [super init]) {
title = NSLocalizedString(@"PROJECTS", nil);
isSubCategory = NO;
// Initialize projects
//!!LINE 32 IS HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
projects = [NSArray arrayWithContentsOfFile:DNPROJECTSFILE];
}
return self;
}
// CATEGORIES
- (NSArray *)subCategories {
NSMutableArray *projectsArray = [[[NSMutableArray alloc] init] autorelease];
for (NSDictionary *project in projects) {
DNCategory *projectCategory = [[DNCategory alloc] initWithTitle:[project valueForKey:@"title"]
subCategories:nil
isSubCategory:YES];
[projectsArray addObject:projectCategory];
[projectCategory release];
}
return projectsArray;
}
DNPROJECTSFILE 的内容
http://gist.github.com/618628
请参阅 INSTRUMENTS
这是控制台在运行时显示的内容(已启用 NSZombie):
run
[Switching to process 41257]
Running…
2010-10-09 23:32:36.899 Done[41257:a0f] *** -[CFString isKindOfClass:]: message sent to deallocated instance 0x1001caab0
sharedlibrary apply-load-rules all
这是 Instruments 在 NSZombie 测试中显示的内容:
僵尸消息
Objective-C 消息已发送到地址为 0x10012af80 的已释放对象(僵尸)。
堆栈跟踪
0 CoreFoundation _CFRuntimeCreateInstance
1 CoreFoundation __CFStringCreateImmutableFunnel3
2 CoreFoundation CFStringCreateWithBytes
3 CoreFoundation _uniqueStringForCharacters
4 CoreFoundation getString
5 CoreFoundation parseXMLElement
6 CoreFoundation parseXMLElement
7 CoreFoundation parseArrayTag
8 CoreFoundation parseXMLElement
9 CoreFoundation parsePListTag
10 CoreFoundation parseXMLElement
11 CoreFoundation _CFPropertyListCreateFromXMLStringError
12 CoreFoundation _CFPropertyListCreateWithData
13 CoreFoundation CFPropertyListCreateFromXMLData
14 Foundation _NSParseObjectFromASCIIPropertyListOrSerialization
15 Foundation +[NSArray(NSArray) newWithContentsOf:immutable:]
16 Foundation +[NSArray(NSArray) arrayWithContentsOfFile:]
17 Done -[DNProjectsCategory init] /Users/rsonic/Developer/Done/DNProjectsCategory.m:32
18 Done -[DNBindingsController categories] /Users/rsonic/Developer/Done/DNBindingsController.m:18
19 Foundation -[NSObject(NSKeyValueCoding) valueForKey:]
20 Foundation -[NSObject(NSKeyValueCoding) valueForKeyPath:]
21 AppKit -[NSBinder valueForBinding:resolveMarkersToPlaceholders:]
22 AppKit -[NSArrayDetailBinder _refreshDetailContentInBackground:]
23 AppKit -[NSObject(NSKeyValueBindingCreation) bind:toObject:withKeyPath:options:]
24 AppKit -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:]
25 AppKit loadNib
26 AppKit +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:]
27 AppKit +[NSBundle(NSNibLoading) loadNibNamed:owner:]
28 AppKit NSApplicationMain
29 Done main /Users/rsonic/Developer/Done/main.m:13
30 Done start
问题
我真的不知道如何修复这个双重释放。据我所知,除了 dealloc
之外,我不会在任何地方释放 projects
变量。有人可以帮我吗?谢谢。
I am creating an application and I get an EXC_BAD_ACCESS error.
CODE
@interface DNProjectsCategory : DNCategory {
NSArray *projects;
}
@property(nonatomic, retain) NSArray *projects;
@end
And:
@implementation DNProjectsCategory
@synthesize projects;
// MEM
- (void)dealloc {
[projects release];
[super dealloc];
}
// INIT.
- (id)init {
if (self = [super init]) {
title = NSLocalizedString(@"PROJECTS", nil);
isSubCategory = NO;
// Initialize projects
//!!LINE 32 IS HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
projects = [NSArray arrayWithContentsOfFile:DNPROJECTSFILE];
}
return self;
}
// CATEGORIES
- (NSArray *)subCategories {
NSMutableArray *projectsArray = [[[NSMutableArray alloc] init] autorelease];
for (NSDictionary *project in projects) {
DNCategory *projectCategory = [[DNCategory alloc] initWithTitle:[project valueForKey:@"title"]
subCategories:nil
isSubCategory:YES];
[projectsArray addObject:projectCategory];
[projectCategory release];
}
return projectsArray;
}
CONTENTS OF DNPROJECTSFILE
See http://gist.github.com/618628
CONSOLE & INSTRUMENTS
This is what the Console says when ran (NSZombie is enabled):
run
[Switching to process 41257]
Running…
2010-10-09 23:32:36.899 Done[41257:a0f] *** -[CFString isKindOfClass:]: message sent to deallocated instance 0x1001caab0
sharedlibrary apply-load-rules all
Here is what Instruments says in an NSZombie test:
Zombie Messaged
An Objective-C message was sent to a deallocated object (zombie) at address: 0x10012af80.
Stack Trace
0 CoreFoundation _CFRuntimeCreateInstance
1 CoreFoundation __CFStringCreateImmutableFunnel3
2 CoreFoundation CFStringCreateWithBytes
3 CoreFoundation _uniqueStringForCharacters
4 CoreFoundation getString
5 CoreFoundation parseXMLElement
6 CoreFoundation parseXMLElement
7 CoreFoundation parseArrayTag
8 CoreFoundation parseXMLElement
9 CoreFoundation parsePListTag
10 CoreFoundation parseXMLElement
11 CoreFoundation _CFPropertyListCreateFromXMLStringError
12 CoreFoundation _CFPropertyListCreateWithData
13 CoreFoundation CFPropertyListCreateFromXMLData
14 Foundation _NSParseObjectFromASCIIPropertyListOrSerialization
15 Foundation +[NSArray(NSArray) newWithContentsOf:immutable:]
16 Foundation +[NSArray(NSArray) arrayWithContentsOfFile:]
17 Done -[DNProjectsCategory init] /Users/rsonic/Developer/Done/DNProjectsCategory.m:32
18 Done -[DNBindingsController categories] /Users/rsonic/Developer/Done/DNBindingsController.m:18
19 Foundation -[NSObject(NSKeyValueCoding) valueForKey:]
20 Foundation -[NSObject(NSKeyValueCoding) valueForKeyPath:]
21 AppKit -[NSBinder valueForBinding:resolveMarkersToPlaceholders:]
22 AppKit -[NSArrayDetailBinder _refreshDetailContentInBackground:]
23 AppKit -[NSObject(NSKeyValueBindingCreation) bind:toObject:withKeyPath:options:]
24 AppKit -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:]
25 AppKit loadNib
26 AppKit +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:]
27 AppKit +[NSBundle(NSNibLoading) loadNibNamed:owner:]
28 AppKit NSApplicationMain
29 Done main /Users/rsonic/Developer/Done/main.m:13
30 Done start
QUESTION
I really don't know how to fix this double-release. For as far as I know I don't release the projects
variable anywhere except in dealloc
. Can somebody help me, please? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有使用访问器,因此项目永远不会保留。
init 方法有两种选择:
或者
属性“创建”两个方法,一个 getter
- (NSArray *)projects
和一个(在您的情况下更重要)setter- (void)setProjects: (NSArray*)a;
您在属性声明中编写的保留语句仅适用于 setter。如果直接使用projects = foo;
设置变量,则不会使用 setter。但是
self.projects = foo;
相当于[self setProject:foo]
,这是动态创建的 setter。您的 setter 看起来与此类似:
因此,如果您使用 setter,您从 arrayWithContentsOfFile: 获得的自动释放的 NSArray 将被保留。
在 Objective C 中进行的每一个非“alloc”、“copy”、“retain”或任何以 new 开头的调用都会返回一个自动释放的对象。如果您想稍后使用它们(即在您离开创建它们的方法之后),则必须保留它们。
也许您想再看看 Apple内存管理指南
You are not using the accessor, so projects is never retained.
Two choices for your init method:
or
the property "creates" two methods, a getter
- (NSArray *)projects
and a, in your case more important, setter- (void)setProjects:(NSArray*)a;
The retain statement which you wrote in your property declaration only applies to the setter. If you set the variable directly withprojects = foo;
the setter is not used.But
self.projects = foo;
is equivalent to[self setProject:foo]
, which is your dynamically created setter.Your setter looks similar to this:
So if you use the setter, your autoreleased NSArray you got from arrayWithContentsOfFile: is retained.
Every call you make in Objective C that is not "alloc", "copy", "retain" or anything starting with new returns an autoreleased object. You have to retain those if you want to use them later (i.e. after you left the method where they were created).
Maybe you want to take another look at the Apple Memory Managment Guide