消息发送到已释放的实例

发布于 2024-11-24 22:20:51 字数 3908 浏览 1 评论 0原文

我正在使用 TouchXML 来解析 iOS 中的元素。我使用 NSIncationOperation 从 Web 服务检索响应,然后解析并显示结果。一切正常,因为后台线程使用 [self PerformSelectorOnMainThread:@selector(displayLoginresult:) withObject:res waitUntilDone:NO]; 在主线程上显示结果,但随后出现错误:

2011-07-18 11:58:06.108 billsApp[873:7107] *** -[CFString release]: message sent to deallocated instance 0x5d809b0

要解析的代码元素是:

-(LoginResult *) tryLogin:(NSString *)userName withPassword:(NSString*)password{
    NSURL *url = [UrlUtility TryLogin:userName passwordHash:password];
    CXMLDocument *responseObj = [UrlUtility xmlDocWithUrl:url];
    if(responseObj == [NSNull null])
        return [NSNull null];

    CXMLElement *eleUser = [responseObj nodeForXPath:@"//User" error:nil];
    CXMLElement *eleResult = [responseObj nodeForXPath:@"//Result" error:nil]; 
    LoginResultType resultType;
    //NSLog(@"Result: ");
    //NSLog(eleResult );
//  NSLog([[eleResult stringValue] lowercaseString]);
    if ([[[eleResult stringValue] lowercaseString ] isEqualToString: @"successful"]){
        resultType = Successful;
    } else {
        resultType = InvalidUsernameOrPassword;
    }

    LoginResult *res = [[LoginResult alloc] init];
    res.result = resultType;

    for (CXMLElement *resultElement in [responseObj children] ) {
        NSLog([NSString stringWithFormat:@"%@ %@", [resultElement name], [resultElement stringValue]]);
    }

    //todo: fix enum parsing =[LoginResult loginResultTypeStringToEnum: [eleResult  stringValue]];  

    if(eleUser != nil) {
        CXMLElement *eleClientID = [eleUser nodeForXPath:@"ClientID" error:nil];
        CXMLElement *eleCompanyName = [eleUser nodeForXPath:@"CompanyName" error:nil];
        CXMLElement *eleCompanyContact = [eleUser nodeForXPath:@"CompanyContact" error:nil];
        CXMLElement *eleIsAgent = [eleUser nodeForXPath:@"IsAgent" error:nil];
        CXMLElement *eleParentID = [eleUser nodeForXPath:@"ParentID" error:nil];

        NSInteger *clientId = [[eleClientID stringValue] integerValue];
        NSString *companyName = [eleCompanyName stringValue];
        NSString *companyContact = [eleCompanyContact stringValue];
        bool isAgent = [Utils stringToBool:[eleIsAgent stringValue]];
        NSInteger *parentId = [[eleParentID stringValue] integerValue];
        User *user = [[User alloc] initWithData:clientId companyName:companyName companyContact:companyContact isAgent:isAgent parentId:parentId];
        res.user = user;
        // release elements

//      [eleClientID release];
//      [eleCompanyName release];
//      [eleCompanyContact release];
//      [eleIsAgent release];
//      [eleParentID release];

        //release raw values
//      [companyName release];
//      [companyContact release];
    }

//  [eleResult release];
//  [eleUser release];

    return res;
}

我想说这是 TouchXML 的一个错误,但我发现这不太可能。有什么办法可以进一步追踪错误吗?

编辑: User 类的属性定义为:

@property (nonatomic, readwrite) NSInteger clientId;
@property (nonatomic, retain) NSString *companyName;
@property (nonatomic, retain) NSString *companyContact;
@property (nonatomic, readwrite) bool isAgent;
@property (nonatomic, readwrite) NSInteger parentId;

实例初始化为:

-(User*)initWithData:(NSInteger *)clientId companyName:(NSString *)company companyContact:(NSString*)contact isAgent:(bool)agent parentId:(NSInteger*)parentId {
    //[self = super init];
    self.clientId= clientId;
    self.companyName= company;
    self.companyContact= contact;
    self.isAgent = agent;
    self.parentId = parentId;
    return self;
}

LoginResult 类为:

@interface LoginResult : NSObject {
    LoginResultType result;
    User *user;

    NSString * const loginResultTypeArray[4];
}

@property (nonatomic, readwrite) LoginResultType result;
@property (nonatomic, retain) User *user;

I'm using TouchXML to parse an element in iOS. I retrieve a response from a web service using an NSInvocationOperation, then parse and display the results. Everything works fine as the background thread displays results on the main thread using [self performSelectorOnMainThread:@selector(displayLoginresult:) withObject:res waitUntilDone:NO]; but then I get an error:

2011-07-18 11:58:06.108 billsApp[873:7107] *** -[CFString release]: message sent to deallocated instance 0x5d809b0

The code to parse the element is:

-(LoginResult *) tryLogin:(NSString *)userName withPassword:(NSString*)password{
    NSURL *url = [UrlUtility TryLogin:userName passwordHash:password];
    CXMLDocument *responseObj = [UrlUtility xmlDocWithUrl:url];
    if(responseObj == [NSNull null])
        return [NSNull null];

    CXMLElement *eleUser = [responseObj nodeForXPath:@"//User" error:nil];
    CXMLElement *eleResult = [responseObj nodeForXPath:@"//Result" error:nil]; 
    LoginResultType resultType;
    //NSLog(@"Result: ");
    //NSLog(eleResult );
//  NSLog([[eleResult stringValue] lowercaseString]);
    if ([[[eleResult stringValue] lowercaseString ] isEqualToString: @"successful"]){
        resultType = Successful;
    } else {
        resultType = InvalidUsernameOrPassword;
    }

    LoginResult *res = [[LoginResult alloc] init];
    res.result = resultType;

    for (CXMLElement *resultElement in [responseObj children] ) {
        NSLog([NSString stringWithFormat:@"%@ %@", [resultElement name], [resultElement stringValue]]);
    }

    //todo: fix enum parsing =[LoginResult loginResultTypeStringToEnum: [eleResult  stringValue]];  

    if(eleUser != nil) {
        CXMLElement *eleClientID = [eleUser nodeForXPath:@"ClientID" error:nil];
        CXMLElement *eleCompanyName = [eleUser nodeForXPath:@"CompanyName" error:nil];
        CXMLElement *eleCompanyContact = [eleUser nodeForXPath:@"CompanyContact" error:nil];
        CXMLElement *eleIsAgent = [eleUser nodeForXPath:@"IsAgent" error:nil];
        CXMLElement *eleParentID = [eleUser nodeForXPath:@"ParentID" error:nil];

        NSInteger *clientId = [[eleClientID stringValue] integerValue];
        NSString *companyName = [eleCompanyName stringValue];
        NSString *companyContact = [eleCompanyContact stringValue];
        bool isAgent = [Utils stringToBool:[eleIsAgent stringValue]];
        NSInteger *parentId = [[eleParentID stringValue] integerValue];
        User *user = [[User alloc] initWithData:clientId companyName:companyName companyContact:companyContact isAgent:isAgent parentId:parentId];
        res.user = user;
        // release elements

//      [eleClientID release];
//      [eleCompanyName release];
//      [eleCompanyContact release];
//      [eleIsAgent release];
//      [eleParentID release];

        //release raw values
//      [companyName release];
//      [companyContact release];
    }

//  [eleResult release];
//  [eleUser release];

    return res;
}

Part of me wants to say it's a bug with TouchXML, but I find that very unlikely. Is there any way to further track down the error?

EDIT: The definitions for the properties on the User class is:

@property (nonatomic, readwrite) NSInteger clientId;
@property (nonatomic, retain) NSString *companyName;
@property (nonatomic, retain) NSString *companyContact;
@property (nonatomic, readwrite) bool isAgent;
@property (nonatomic, readwrite) NSInteger parentId;

And the instance is initialized with:

-(User*)initWithData:(NSInteger *)clientId companyName:(NSString *)company companyContact:(NSString*)contact isAgent:(bool)agent parentId:(NSInteger*)parentId {
    //[self = super init];
    self.clientId= clientId;
    self.companyName= company;
    self.companyContact= contact;
    self.isAgent = agent;
    self.parentId = parentId;
    return self;
}

And the LoginResult class is:

@interface LoginResult : NSObject {
    LoginResultType result;
    User *user;

    NSString * const loginResultTypeArray[4];
}

@property (nonatomic, readwrite) LoginResultType result;
@property (nonatomic, retain) User *user;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无声情话 2024-12-01 22:20:51

尝试一下:您是否在 User 类中正确保留了 companyNamecompanyContatct

编辑:

接下来我要检查的是 loginResultTypeArray。字符串是如何分配给它的?我想这个建议对你来说也是微不足道的,但是用这么少的代码提出有用的建议真的很困难......

你不能了解一下 which CFString 实际上正在发布吗?如果它不是自动释放的对象,堆栈跟踪可能会指向发送 release 消息的方法...这将非常有帮助...

否则,我会尝试 NSLog 一些 NSString 的地址,以便您可以将它们与错误日志中找到的地址进行比较(并且再次尝试找出释放后实际重用的字符串)。

最后,另一种找出删除后使用哪个字符串的方法可能是使用方法调配,在调用调配的 < code>dealloc,对对象进行一些日志记录。这将产生大量日志信息,但是知道字符串的地址,您可以轻松找到所需的内容。 此处查找有关 swizzling 的信息。

Just a try: are you correctly retaining companyName and companyContatct in your User class?

EDIT:

Next thing I would check is loginResultTypeArray. How are string assigned to it? I guess that this advice will also sound trivial to you, but it is really difficult to come up with useful suggestion with so little code...

Can't you get some idea about which CFString is actually being released? If it is not an autoreleased object, possibly the stack trace could point at the method which is sending the release message... this would be very helpful...

Otherwise, I would try and NSLog some of your NSStrings addresses, so that you can compare them with the address you find in the error log (and, again, try and find out which string was actually reused after deallocation).

Finally, another approach to find out which string is used after deletion could be using method swizzling to replace NSString's dealloc with a method of yours that, before calling the swizzled dealloc, does some logging of the objec. This will produce much log info, but knowing the address of the string you could find easily what you need. Find here info about swizzling.

玩心态 2024-12-01 22:20:51

追踪这件事简直就是一场噩梦。我有一个返回 NSString * 的方法,然后由另一个方法解析它以生成 XML 文档,然后由第二个方法释放。我实际上需要在第一种方法中自动释放它。

This was a nightmare to track down. I had a method which returned an NSString *, which was then parsed by another method to produce an XML document, then release by the second method. I actually needed to autorelease it in the first method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文