I am creating an application and I get an EXC_BAD_ACCESS error.
@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;
}
See http://gist.github.com/618628
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
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.
You are not using the accessor, so projects is never retained. Two choices for your init method:
projects = [[NSArray arrayWithContentsOfFile:DNPROJECTSFILE] retain];
or
self.projects = [NSArray arrayWithContentsOfFile:DNPROJECTSFILE];
@property(nonatomic, retain) NSArray *projects;
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 with projects = 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:
- (void)setProjects:(NSArray*)anArray {
[anArray retain];
[projects release];
projects = anArray;
}
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