xcode RespondsToSelector 发送到释放的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3591740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
respondsToSelector send to deallocated object
提问by testing
I try to find out why my app crashes (RSS Reader) if I send a wrong URL to NSXML Parser. I got an EXC_BAD_ACCES
S. So after some Searching I found out that I have to use Zombies. So I added the following arguments to the environment:
如果我向 NSXML Parser 发送错误的 URL,我会尝试找出我的应用程序崩溃的原因(RSS 阅读器)。我得到了一个EXC_BAD_ACCES
S。所以经过一些搜索我发现我必须使用 Zombies。所以我在环境中添加了以下参数:
CFZombieLevel = 3
NSMallocStaclLogging = YES
NSDeallocateZombies = NO
MallocStackLoggingNoCompact = YES
NSZombieEnabled = YES
NSDebugEnabled = YES
NSAutoreleaseFreedObjectCheckEnabled = YES
I also added malloc_error_break
as breakpoint. Then I added some other breakpoints in the GUI and pressed Build and Debug. In the console I get the following message:
我还添加malloc_error_break
了断点。然后我在 GUI 中添加了一些其他断点并按下 Build 和 Debug。在控制台中,我收到以下消息:
2010-08-28 18:41:49.761 RssReader[2850:207] *** -[XMLParser respondsToSelector:]: message sent to deallocated instance 0x59708e0
2010-08-28 18:41:49.761 RssReader[2850:207] *** -[XMLParser respondsToSelector:]: message sent to deallocated instance 0x59708e0
Sometimes I also get the following message:
wait_fences: failed to receive reply: 10004003
有时我也会收到以下消息:
wait_fences: failed to receive reply: 10004003
If I type in "shell malloc_history 2850 0x59708e0" I get the following:
如果我输入“shell malloc_history 2850 0x59708e0”,我会得到以下信息:
...
ALLOC 0x5970870-0x59709d7 [size=360]: thread_a0aaa500 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | PurpleEventCallback | _UIApplicationHandleEvent | -[UIApplication sendEvent:] | -[UIApplication handleEvent:withNewEvent:] | -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] | -[UIApplication
...
----
FREE 0x5970870-0x59709d7 [size=360]: thread_a0aaa500 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | PurpleEventCallback | _UIApplicationHandleEvent | -[UIApplication sendEvent:] | -[UIApplication handleEvent:withNewEvent:] | -[UIApplication
...
ALLOC 0x59708e0-0x597090f [size=48]: thread_a0aaa500 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | PurpleEventCallback | _UIApplicationHandleEvent | -[UIApplication sendEvent:] | -[UIApplication handleEvent:withNewEvent:] | -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] | -[UIApplication
...
Binary Images:
0x1000 - 0x6ff3 +RssReader ??? (???) <6EBB16BC-2BCE-CA3E-C76E-F0B078995E2D> /Users/svp/Library/Application Support/iPhone Simulator/4.0.1/Applications/AF4CE7CA-88B6-44D4-92A1-F634DE7B9072/RssReader.app/RssReader
0xe000 - 0x1cfff3 +Foundation 751.32.0 (compatibility 300.0.0) <18F9E1F7-27C6-2B64-5B9D-BAD16EE5227A>
...
What does this mean? How do I know which object 0x59708e0 is? I can't find the code which causes my app to crash. The only thing I know is that it should be a respondsToSelector message. I added a breakpoint to all my respondsToSelector messages. They get hitted but the app crashes not at that point. I also tried to comment them out except for one and also gets the app crashing. The one which was not commented out, wasn't hit. Where do I have a memory leak?
这是什么意思?我怎么知道 0x59708e0 是哪个对象?我找不到导致我的应用程序崩溃的代码。我唯一知道的是它应该是一个 RespondsToSelector 消息。我在我所有的 RespondsToSelector 消息中添加了一个断点。他们被击中,但应用程序不会在那时崩溃。除了一个之外,我还尝试将它们注释掉,并且还导致应用程序崩溃。没有被注释掉的那个,没有被击中。我在哪里有内存泄漏?
The next confusing thing is that NSXML Parser continue its' work, despite the parseErrorOccurred delegate is called. After two times an error is thrown, the app crashes.
下一个令人困惑的事情是 NSXML Parser 继续其工作,尽管 parseErrorOccurred 委托被调用。两次抛出错误后,应用程序崩溃。
Why is Zombies in the Run with Peformance Tool disabled?
为什么禁用了性能工具运行中的僵尸?
Edit:
编辑:
Now I used this instruction (not able to post. sorry. spam prevention) I got this working. What is the meaning of this?
现在我使用了这个指令(无法发布。抱歉。垃圾邮件预防)我得到了这个工作。这是什么意思?
@Graham:
In my parser class I instantiate NSXMLParser
:
@Graham:在我的解析器类中,我实例化NSXMLParser
:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
...
NSXMLParser *rssParser = [[NSXMLParser alloc] initWithData:responseData];
[rssParser setDelegate:self];
...
[rssParser parse];
//[rssParser release];
}
During I searched the error, I commented out the release method. Currently rssParser never get's released in the parser class.
在我搜索错误的过程中,我注释掉了release方法。目前 rssParser 永远不会在解析器类中发布。
In my RootViewController
class I instantiate my parser:
在我的RootViewController
课堂上,我实例化了我的解析器:
- (void)loadData {
if (newsItems == nil) {
[activityIndicator startAnimating];
XMLParser *rssParser = [[XMLParser alloc] init];
[rssParser parseRssFeed:@"http://feeds2.feedburner.com/TheMdnShowtest" withDelegate:self];
[rssParser release];
rssParser = nil;
} else {
[self.tableView reloadData];
}
}
If I don't release it here, it doesn't crash. But for each alloc I have to do a release? Or should I autorelease NSXMLParser
in connectionDidFinishLoading
?
如果我不在这里释放它,它就不会崩溃。但是对于每个分配我必须做一个释放?或者我应该自动释放NSXMLParser
的connectionDidFinishLoading
?
采纳答案by testing
In RootViewController.h I have declared the property rssParser:
在 RootViewController.h 中,我已经声明了属性 rssParser:
@class XMLParser;
@interface RootViewController : UITableViewController {
...
XMLParser *rssParser;
}
...
@property (retain, nonatomic) XMLParser *rssParser;
@end
In RootViewController.m I have a method called errorOccurred:
在 RootViewController.m 中,我有一个名为 errorOccurred 的方法:
- (void)errorOccurred {
[rssParser release];
rssParser = nil;
if ([activityIndicator isAnimating]) {
[activityIndicator stopAnimating];
}
}
In my XMLParser.m file I call the errorOccurred two times:
在我的 XMLParser.m 文件中,我调用了 errorOccurred 两次:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
...
if ([_delegate respondsToSelector:@selector(errorOccurred)])
[_delegate errorOccurred];
else
{
[NSException raise:NSInternalInconsistencyException
format:@"Delegate doesn't respond to errorOccurred:"];
}
}
To see how _delegate is declared, look at the tutorial http://www.cocoadevblog.com/iphone-tutorial-creating-a-rss-feed-reader. It is an id variable and has a own setter and getter method (you can also declare it as property I think). The second time:
要了解 _delegate 是如何声明的,请查看教程http://www.cocoadevblog.com/iphone-tutorial-creating-a-rss-feed-reader。它是一个 id 变量,并且有自己的 setter 和 getter 方法(我认为您也可以将其声明为属性)。第二次:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
...
if ([_delegate respondsToSelector:@selector(errorOccurred)])
[_delegate errorOccurred];
else
{
[NSException raise:NSInternalInconsistencyException
format:@"Delegate doesn't respond to errorOccurred:"];
}
}
The release of my rssParser variables are like the following:
我的 rssParser 变量的释放如下:
In loadData in RootViewController.m I never release it. Unfortunately it will crash if I do it in loadData. It is only released if a error occurred (see above) or in the dealloc method. But I think that should work fine as it is declared as property.
在 RootViewController.m 中的 loadData 中,我从不释放它。不幸的是,如果我在 loadData 中执行它会崩溃。只有在发生错误时(见上文)或在 dealloc 方法中才会释放它。但我认为这应该可以正常工作,因为它被声明为财产。
- (void)loadData {
if (newsItems == nil) {
[activityIndicator startAnimating];
self.rssParser = [[XMLParser alloc] init];
[rssParser parseRssFeed:@"http://www.wrongurl.com/wrongrss.xml" withDelegate:self];
} else {
[self.tableView reloadData];
}
}
In XMLParser.m I release it after the parse method:
在 XMLParser.m 中,我在 parse 方法之后释放它:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
...
NSXMLParser *rssParser = [[NSXMLParser alloc] initWithData:responseData];
[rssParser setDelegate:self];
[rssParser parse];
[rssParser release];
rssParser = nil;
}
Note that the two variable names are the same (rssParser), but they are different. In RootViewController I'm creating an instance of XMLParser, and in XMLParser.m I'm creating an instance of NSXMLParser.
注意两个变量名是一样的(rssParser),但是是不同的。在 RootViewController 中,我创建了一个 XMLParser 实例,在 XMLParser.m 中我创建了一个 NSXMLParser 实例。
So I think I'll leave it at that, until I'm not experiencing a new error or someone of you explain me why this is bad.
所以我想我会保留它,直到我没有遇到新的错误或者你们中的某个人向我解释为什么这很糟糕。
回答by rano
Zombie is disabled as you use it with Memory Leaks since all Zombies would be signaled as leaks. To run the Zombie tool you can go to the Instrument menu and do File>New and chose the Zombie tool alone, doing so the program will stop if a zombie has received a message and you'll be given a link in a small pop up to that zombie object and its history
当您将 Zombie 与 Memory Leaks 一起使用时,它会被禁用,因为所有 Zombie 都会被标记为泄漏。要运行 Zombie 工具,您可以转到 Instrument 菜单并执行 File>New 并单独选择 Zombie 工具,如果僵尸收到消息,程序将停止,您将在一个小弹出窗口中获得一个链接到那个僵尸对象和它的历史
回答by Graham Perks
Somewhere you're allocating the XMLParser. Let's see that code. You're not auto-releasing it, are you?
您正在分配 XMLParser 的地方。让我们看看那个代码。你不会自动释放它,是吗?
Somewhere it's getting released... is it assigned to a property? Let's see that property definition.
它在某个地方被释放......它是否被分配给了一个财产?让我们看看属性定义。
Later on the respondsToSelector: method is being invoked, but that could be any method. The point is that your XMLParser got released before you intended.
稍后,将调用respondsToSelector: 方法,但这可以是任何方法。关键是您的 XMLParser 在您打算之前发布了。
回答by Kevin Teman
Do you also have rssParser, the same instance variable you've set to release here...
您是否也有 rssParser,您在此处设置要发布的相同实例变量...
- (void)errorOccurred {
[rssParser release];
rssParser = nil;
if ([activityIndicator isAnimating]) {
[activityIndicator stopAnimating];
}
}
...released in your dealloc method? This would cause a double release and thus EXEC_BAD_ACCESS.
...在您的 dealloc 方法中发布?这将导致双重释放,从而导致 EXEC_BAD_ACCESS。