Iphone respondsToSelector发送到解除分配的对象

Iphone respondsToSelector发送到解除分配的对象,iphone,objective-c,xcode,debugging,nszombie,Iphone,Objective C,Xcode,Debugging,Nszombie,如果我向NSXML解析器发送了错误的URL,我试图找出我的应用程序(RSS阅读器)崩溃的原因。我得到了一个EXC\u BAD\u ACCESS。所以经过一些搜索,我发现我必须使用僵尸。因此,我在环境中添加了以下参数: CFZombieLevel = 3 NSMallocStaclLogging = YES NSDeallocateZombies = NO MallocStackLoggingNoCompact = YES NSZombieEnabled = YES NSDebugEnabled

如果我向NSXML解析器发送了错误的URL,我试图找出我的应用程序(RSS阅读器)崩溃的原因。我得到了一个
EXC\u BAD\u ACCES
S。所以经过一些搜索,我发现我必须使用僵尸。因此,我在环境中添加了以下参数:

CFZombieLevel = 3
NSMallocStaclLogging = YES
NSDeallocateZombies = NO
MallocStackLoggingNoCompact = YES
NSZombieEnabled = YES
NSDebugEnabled = YES
NSAutoreleaseFreedObjectCheckEnabled = YES
我还添加了
malloc\u error\u break
作为断点。然后,我在GUI中添加了一些其他断点,并按下Build和Debug。在控制台中,我收到以下消息:

2010-08-28 18:41:49.761 RssReader[2850:207]***-[XMLParser respondsToSelector:]:发送到解除分配实例0x59708e0的消息

有时我也会收到以下信息:
wait\u fences:未能接收回复:10004003

如果我输入“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>
...
在搜索错误的过程中,我注释掉了release方法。目前rssParser从未在解析器类中发布过

在我的
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];  
    }  
}

如果我不在这里释放它,它不会崩溃。但是对于每一个alloc,我都要做一个释放?或者我应该在
connectiondFinishLoading
中自动释放
NSXMLParser

当您将僵尸与内存泄漏一起使用时,它将被禁用,因为所有僵尸都将被标记为泄漏。要运行僵尸工具,您可以转到Instrument菜单并执行File>New并单独选择僵尸工具,这样做,如果僵尸收到消息,程序将停止,您将在一个小弹出窗口中获得一个链接,指向正在分配XMLParser的某个位置的僵尸对象及其历史。让我们看看代码。你不是在自动释放它吧

在某个地方它被释放了。。。它是分配给一个属性的吗?让我们看看属性定义


稍后将调用respondsToSelector:method,但该方法可以是任何方法。关键是您的XMLParser在您打算发布之前就发布了。

在RootViewController.h中,我声明了属性rssParser:

@class XMLParser;

@interface RootViewController : UITableViewController {
    ...
    XMLParser *rssParser;
}
...
@property (retain, nonatomic) XMLParser *rssParser;

@end
在RootViewController.m中,我有一个名为erroroccurrent的方法:

- (void)errorOccurred {
    [rssParser release];
    rssParser = nil;
    if ([activityIndicator isAnimating]) {
        [activityIndicator stopAnimating];
    }
}
在我的XMLParser.m文件中,我调用了两次错误:

- (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:"];  
    }
}
要了解如何声明_delegate,请查看教程。它是一个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:"];  
    }
}  
my rssParser变量的发布如下所示:

...
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>
...
在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];  
    }  
}
在XMLParser.m中,我在解析方法之后释放它:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {  
   ...

    NSXMLParser *rssParser = [[NSXMLParser alloc] initWithData:responseData];

    [rssParser setDelegate:self];

    [rssParser parse];

    [rssParser release];
    rssParser = nil;
}  
请注意,这两个变量名相同(rssParser),但不同。在RootViewController中,我创建了一个XMLParser实例,在XMLParser.m中,我创建了一个NSXMLParser实例


所以我想我会一直保持这个状态,直到我没有遇到新的错误,或者你们中的某个人向我解释为什么这不好。

你们也有rssParser吗,就是你们在这里发布的同一个实例变量

- (void)errorOccurred {
    [rssParser release];
    rssParser = nil;
    if ([activityIndicator isAnimating]) {
        [activityIndicator stopAnimating];
    }
}

…以您的dealloc方法发布?这将导致双重释放,因此执行错误访问。

谢谢提示!我在阅读时意识到了这一点,我不知道Instruments是一个独立的程序,而不是Xcode的一部分。然而,我不明白为什么他们会提供菜单项,如果它不能被使用的话。所以我编辑了我的问题。我正在使用alloc,所以我不认为我正在自动删除它。我不使用RSS解析器作为属性。何时发布它?看起来您的XMLParser类需要一些异步I/O响应?如果是这样的话,它需要等待直到完成。因此,您不能在loadData中释放它。在ConnectionIDFinishLoading中自动释放自身:如果在完成处理时,值得一试。在任何连接错误处理方法中也必须这样做。我没有仔细阅读同步/异步的内容。所以我告诉你我用什么。我使用NSURLConnection和NSXMLParser。NSURLConnection正在创建异步连接,NSXMLParser是SAX解析器。因为我在ConnectionIDFinishLoading中开始解析:解析发生在文件下载时(错误文件是HTML文件,重定向在5秒后发生)。该项目基于本教程:。很好!这个问题太老了,我记不得了。很抱歉在我当前的项目中,
errorOccursed
中不再有发布。