arrayWithContentsOfFile:导致崩溃

发布于 2024-09-26 11:19:54 字数 3640 浏览 0 评论 0原文

我正在创建一个应用程序,但收到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玩套路吗 2024-10-03 11:19:54

您没有使用访问器,因此项目永远不会保留。
init 方法有两种选择:

projects = [[NSArray arrayWithContentsOfFile:DNPROJECTSFILE] retain];

或者

self.projects = [NSArray arrayWithContentsOfFile:DNPROJECTSFILE];

@property(nonatomic, retain) NSArray *projects;

属性“创建”两个方法,一个 getter - (NSArray *)projects 和一个(在您的情况下更重要)setter - (void)setProjects: (NSArray*)a; 您在属性声明中编写的保留语句仅适用于 setter。如果直接使用 projects = foo; 设置变量,则不会使用 setter。
但是 self.projects = foo; 相当于 [self setProject:foo],这是动态创建的 setter。
您的 setter 看起来与此类似:

- (void)setProjects:(NSArray*)anArray {
    [anArray retain];
    [projects release];
    projects = anArray;
}

因此,如果您使用 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:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文