简体   繁体   English

内存泄漏与XML解析器中的NSMutableString

[英]Memory Leak with NSMutableString in XML parser

I'm using an XMLparser within my App. 我在我的应用程序中使用XMLparser。 It's running fine however when I run my App in instruments I keep getting memory leaks at a NSMutableString which handles the strings which came out of the XML. 它运行正常,但是当我在仪器中运行我的应用程序时,我不断在NSMutableString中获取内存泄漏,NSMutableString处理来自XML的字符串。

Weard thing is that this memory leak only occurs when I do a specific call (login) for the second time. Weard事情是这次内存泄漏只在我第二次进行特定呼叫(登录)时发生。 When I do other calls I don't get a memory leak. 当我做其他调用时,我没有内存泄漏。

The NSMutableString which gives the leaks is 'textInProgress'. 给出泄漏的NSMutableString是'textInProgress'。

- (NSDictionary *)objectWithData:(NSData *)data
{


    [dictionaryStack release];
    [textInProgress release];

    dictionaryStack = [[NSMutableArray alloc] init];
    textInProgress = [[NSMutableString alloc] init];

    [dictionaryStack addObject:[NSMutableDictionary dictionary]];

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    parser.delegate = self;
    BOOL success = [parser parse];
    [parser release];

    if (success)
    {

        NSDictionary *resultDict = [dictionaryStack objectAtIndex:0];
        return resultDict;
    }

    return nil;
}


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    NSMutableDictionary *parentDict = [dictionaryStack lastObject];
    NSMutableDictionary *childDict = [NSMutableDictionary dictionary];

    [childDict setObject:attributeDict forKey: NODE_ATTR_KEY];

    id existingValue = [parentDict objectForKey:elementName];
    if (existingValue)
    {
        NSMutableArray *array = nil;
        if ([existingValue isKindOfClass:[NSMutableArray class]])
        {
            array = (NSMutableArray *) existingValue;
        }
        else
        {
            array = [NSMutableArray array];
            [array addObject:existingValue];

            [parentDict setObject:array forKey:elementName];
        }

        [array addObject:childDict];
    }
    else
    {

        [parentDict setObject:childDict forKey:elementName];
    }

    [dictionaryStack addObject:childDict];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    NSMutableDictionary *dictInProgress = [dictionaryStack lastObject];

    if ([textInProgress length] > 0)
    {
        [dictInProgress setObject:textInProgress forKey:NODE_VALUE_KEY];

        [textInProgress release];

        textInProgress = [[NSMutableString alloc] init]; <--- Object leaks here

    }

    [dictionaryStack removeLastObject];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

    [textInProgress appendString:string]; <--- Object leaks here

}

I've been debuggin all day and still can't find a solution for this problem. 我整天都在调试,但仍无法找到解决此问题的方法。 The leak only contains 64 bytes of data. 泄漏仅包含64字节的数据。

Here are also two screenshots of the leak within instruments -> Leaks -> Call tree 这里还有两个仪器泄漏的屏幕截图 - >泄漏 - >调用树 在XML解析器foundCharacters泄漏

XML解析器didEndElement泄漏

Hope someone can help me out! 希望有人能帮助我!


EDIT: 编辑:

The solution for these leaks was to declare the NSMutableString and NSMutableDictionary as a property. 这些泄漏的解决方案是将NSMutableString和NSMutableDictionary声明为属性。 (Refer to Neal his comment) (请参阅Neal他的评论)

I would advise that you convert textInProgress to a property rather than an ivar. 我建议您将textInProgress转换为属性而不是ivar。 Like this: 像这样:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    NSMutableDictionary *dictInProgress = [dictionaryStack lastObject];

    if ([self.textInProgress length] > 0) {

        [dictInProgress setObject:self.textInProgress forKey:NODE_VALUE_KEY];

        self.textInProgress = [NSMutableString string];
    }

    [dictionaryStack removeLastObject];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

    [self.textInProgress appendString:string];
}

And just make sure that you release it in dealloc 并确保您以dealloc发布它

Protip: If you change the name of the property's corresponding ivar as well (eg _textInProgress ), you will get a build error at each point where you used the ivar before, so you won't miss any changes from textInProgress to self.textInProgress Protip:如果你也改变了属性对应的ivar的名称(例如_textInProgress ),你将在之前使用过ivar的每个点都出现构建错误,所以你不会错过从textInProgressself.textInProgress任何更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM