嘿。我一直在研究Twitter应用程序,并且已经在EXC_ BAD_ ACCESS错误上停留了很长时间。我知道EXC_ BAD_ ACCESS是一个内存问题,但我无法确定问题所在。这是我的代码示例:
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = @"/Volumes/Schools/BHS/Student/740827/Documents/Forrest McIntyre CS193P/Presence2";
NSArray *propList = [NSArray arrayWithContentsOfFile:[NSBundle pathForResource:@"TwitterUsers" ofType:@"plist" inDirectory:path]];
people = [[NSMutableArray alloc]init];
for (NSString *name in propList) {
Person *p = [[Person alloc] initWithUserName: name];
[people addObject: p];
[p release];
}
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
在评论后的最后一个大括号上抛出异常。我相信它确实被扔进了某个地方的for循环中,但只是出现了。
以下是Person的实现文件:
@implementation Person
@synthesize image;
@synthesize username;
@synthesize displayName;
@synthesize statusArray;
-(id)initWithUserName:(NSString *)userName {
if(self = [super init])
{
self.username = userName;
NSDictionary *info = [TwitterHelper fetchInfoForUsername:userName];
self.displayName = [info objectForKey:@"name"];
NSLog([NSString stringWithFormat:@"%@",[info objectForKey:@"profile_image_url"]]);
NSString *imageURL2 = [NSString stringWithFormat:@"%@",[info objectForKey:@"profile_image_url"]];
self.image = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: imageURL2]]];
[info release];
self.statusArray = [TwitterHelper fetchTimelineForUsername:userName];
}
return self;
}
@end
感谢您的帮助
编辑:这是PersonListViewController的头文件(包含ViewDidLoad的类)。 这只是为了向您展示人们的来源。
@interface PersonListViewController : UITableViewController {
NSMutableArray *people;
}
@end
答案 0 :(得分:9)
因为您永远不会保留propList
或path
,所以您不应该发布它们。
但是,您应该发布people
有关内存管理的概述,请参阅Memory Management Programming Guide
要快速修复,请尝试使用静态分析器。
答案 1 :(得分:3)
我认为问题在于:
[propList release];
由于您使用arrayWithContentsOfFile
创建了propList,因此无需释放它 - 它将自动释放。自动释放实际上是导致错误的原因,因为它试图释放您已经手动释放的内容。
ETA:正如cobbal所提到的,你也不需要发布path
。
答案 2 :(得分:1)
调试EXC_BAD_ACCESS很难调试。将消息发送到已释放的对象时会发生这种情况。您需要通过启用NSZombiEnabled环境变量来找出导致此一般错误的原因,以便Objective-C环境能够“跟踪”解除分配的对象。使用此功能,当您收到错误时,您可以通过查看调用堆栈来确定错误发生的位置。你不会知道它的发布地点,但至少它会让你接近。
我没有在这里设置它,但你也可能传递一个指向错误的指针,这将导致该对象不会像僵尸/虚拟一样持久存在。
最重要的是,您需要确保要释放的变量,并在必要时保留它们。
Apple的技术问答A给出了Finding bugs with EXC_BAD_ACCESS的提示。
答案 3 :(得分:1)
首先,在您的示例中,这些都不是必需的:
[path release];
[propList release];
,因为:
path
是一个字符串文字(将永远存在)
propList
已自动释放
答案 4 :(得分:1)
对于任何EXC_BAD_ACCESS错误,您通常会尝试向已发布的对象发送消息。追踪这些内容的最佳方式是使用NSZombieEnabled。
这可以通过永远不会实际释放一个对象,但将其包装为“僵尸”并在其中设置一个标志,表示它通常会被释放。这样,如果您再次尝试访问它,它仍然知道在发生错误之前它是什么,并且通过这些信息,您通常可以回溯以查看问题所在。
当调试器有时会抓取任何有用的信息时,它特别有助于后台线程。
非常重要但是,您需要100%确保这只是在您的调试代码而不是您的分发代码中。因为什么都没有发布,你的应用程序将泄漏,泄漏和泄漏。为了提醒我这样做,我把这个日志放在我的appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
如果您需要帮助查找确切的行,请执行构建和调试( CMD-Y )而不是构建并运行( CMD-R )。当应用程序崩溃时,调试器会向您显示确切的行,并与NSZombieEnabled结合使用,您应该能够确切地找到原因。
答案 5 :(得分:0)
http://www.cocoadev.com/index.pl?NSZombieEnabled可用于跟踪EXC_BAD_ACCESS错误。它们不是在release
时解除分配对象,而是将它们置于僵尸状态,当随后访问它们时会引发异常。请确保不要使用此标志设置释放代码,因为它会像筛子那样泄漏内存。
答案 6 :(得分:0)
什么是self.editButtonItem?我没有在你的.h文件中看到它
答案 7 :(得分:0)
有几件事。
在initWithUserName:
中,您从不包含alloc / copy / create的方法获取信息。此外,您没有明确保留它。然而你释放了它。根据Cocoa Memory管理规则,假设fetchInfoForUsername:
按预期自动释放其结果,这是有问题的。
在初始值设定项中使用属性访问器被认为是错误的形式,因为它可能会导致KVO通知被发送给半生不熟的实例。