解除分配变量时获取段错误(EXC_BAD_ACCESS)

时间:2009-02-18 21:16:29

标签: iphone objective-c cocoa-touch memory-management

好的我明白这个错误主要来自发送方法调用或尝试访问已经解除分配的变量。

问题在于:

.h
@interface TimeEntry : NSObject <NSCopying, NSCoding> {

NSDate *from;
NSDate *to;

NSString *information;


}

@property (nonatomic, retain) NSDate *from;
@property (nonatomic, retain) NSDate *to;

@property (nonatomic, copy) NSString *information;

@end

我的班级'dealloc。

-(void)dealloc{

    [super dealloc];    
    [to release];
    [from release];
    [information release];

}

当我收到EXC_BAD_ACCESS错误时,这是​​追溯的事情 alt text

所以我正在向已经解除分配的对象发送消息吗?

所以我打开了NSZombie,这停止了我的崩溃。它并没有像我希望的那样给我一些可爱的崩溃报告。相反,它只是让程序不会崩溃。

在上面的dealloc方法中,如果我注释掉[发布]和[从发布]应用程序没有崩溃。如果我只注释其中一个......它不会崩溃。在调试窗口中往返有不同的内存地址。

内存管理怎么这么难!!!!

有人提出任何线索吗?

谢谢,

5 个答案:

答案 0 :(得分:13)

在您释放变量之后发送[super dealloc]消息,而不是之前。 [super dealloc]应该是你在dealloc方法中做的最后一件事。

答案 1 :(得分:2)

请注意,您可以发送[nil release]并且应用程序不会崩溃。 所以在释放之前检查nil是不必要的。

但我同意你应该在dealloc程序的最后做[super dealloc]。

答案 2 :(得分:0)

您应该检查涉及您的属性的所有语句,以查明实际取消分配变量的位置。无论如何,这是一个避免崩溃的快速解决方案,因为当且仅当它们仍然被分配对象时,你的变量才会被释放:

- (无效)的dealloc {

if(to != nil{ 
   NSLog(@"releasing: %@", to);
   [to release];
}

if(from != nil{
   NSLog(@"releasing: %@", from);
   [from release];
}

if(information != nil){
   NSLog(@"releasing: %@", information);
   [information release];
}

[super dealloc]; 

}

此外,您可能需要下载,安装和使用CLANG检查工具来了解代码错误的原因。这个工具(已经为Leopard 10.5.x构建)有时可能无法提供正确的答案,但根据我的个人经验,它从未失败过。我强烈推荐它作为您的日常开发工具之一。

您可以从

下载

http://clang.llvm.org/StaticAnalysis.html

用法非常简单。看看

http://clang.llvm.org/StaticAnalysisUsage.html#BasicUsage

实际上,您只需使用命令

构建Xcode项目

scan-build -k -V xcodebuild

然后,使用在终端窗口中显示为输出的命令检查生成的输出HTML文件。这些文件将为您详细解释代码中出现问题的原因。

亲切的问候

答案 3 :(得分:0)

Terry是正确的,[super dealloc]来电必须始终是-dealloc中的最后一件事。

更具体地说,调用-[NSObject dealloc]就是释放对象的内存。 (在您的情况下,您直接扩展NSObject,但更深层的继承树会创建一系列dealloc调用。)在一般意义上,首先调用父-dealloc方法将释放从父级继承的资源。如果孩子在发布自己的资源时依赖于这些资源,那么你就是一条小溪。由于父母不能依赖孩子,因此首先解除子女资源是正确,安全的做事方式。

答案 4 :(得分:0)

当前对象的属性存储在对象中。

当您调用[super dealloc]时,您告诉系统销毁该对象。在那次电话会议之后,您不能再依赖那里的房产或更正。

如前所述,在释放其他成员后调用它。