我有一个使用以下init方法的类:
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
StateStack* s = [[StateStack alloc] init];
state = s;
[s push:NONE]; //<--EXC_BAD_ACCESS on load here
[s release];
}
return self;
}
StateStack具有以下初始化代码:
- (id)init {
self = [super init];
if (self) {
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
[s release];
NSLog(@"%d",[stack retainCount]);
}
return self;
}
奇怪的是,如果删除NSLog行,EXC_BAD_ACCESS将转移到StateStack的dealloc方法:
- (void)dealloc {
[stack release]; //<--EXC_BAD_ACCESS
[super dealloc];
}
搜索周围似乎暗示EXC_BAD_ACCESS是由过度释放引起的,但我看不出我是如何过度释放的。有谁知道原因可能是什么?
答案 0 :(得分:3)
state = s
没有复制NSMutableArray对象,它只是将指针复制到它。因此,当您调用[s release]
时,s和state引用的对象将被释放。无论何时使用,都可以获得EXC_BAD_ACCESS。
另外,请勿使用[object retainCount]
来调试内存管理问题。它的谎言。 Google NSZombies。
答案 1 :(得分:3)
在init
函数中:
StateStack* s = [[StateStack alloc] init];
state = s;
[s push:NONE]; //<--EXC_BAD_ACCESS on load here
[s release];
您正在分配StateStack
的实例;这得到保留计数1.然后在函数结束时调用release
,保持计数变为0并且对象已准备好被释放。因此,当稍后执行dealloc
时,state
ivar会发送另一个release
,这会导致错误访问。您不需要释放s,因为您希望保留该状态。在另一个init方法中出现相同的错误模式。
这是正确的:
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
StateStack* s = [[StateStack alloc] init];
state = s;
[s push:NONE]; //<--EXC_BAD_ACCESS on load here
}
return self;
}
- (id)init {
self = [super init];
if (self) {
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
}
return self;
}
注意:我不想产生误解。使用保留计数来检查正确的内存分配是没用的。这是真的。无论如何,在保留计数方面的推理有助于理解在分配/释放/自动释放对象时会发生什么。它是基本机制,但是要检查内存管理的正确性是非常困难的。
答案 2 :(得分:1)
- (id)init{ self = [super init]; if (self) { // Initialization code here. state = [[StateStack alloc] init]; [state push:NONE]; } return self; }
StateStack
- (id)init { self = [super init]; if (self) { stack = [[NSMutableArray alloc] init]; } return self;
}