libxml2.2.dylib 造成大量内存泄漏

Posted

技术标签:

【中文标题】libxml2.2.dylib 造成大量内存泄漏【英文标题】:libxml2.2.dylib creating lot of memory leak 【发布时间】:2012-03-29 00:58:33 【问题描述】:

在我的项目中实现 using XpathQuery 时,我很难消除/避免泄漏。目前我正在使用 libXml2.2.dylib 进行解析。当我使用工具检查内存泄漏时,我发现框架中有很多泄漏。

避免这些泄漏的解决方案是什么。记忆对我们来说更重要。如何修复/避免这些漏洞?

【问题讨论】:

@Moshe:没用,libxml2 是一个 C 库。 我们可以使用任何最新版本的 libxml2 不要单独依赖 Instruments - 它可能会引入误报。 【参考方案1】:

如果您使用的是 TFHpple,那么您需要在

中添加以下代码

DictionaryForNode

方法

XPathQuery 类

if (XML_ELEMENT_NODE != currentNode->type) 
    return nil;

所以你的最终方法应该看起来像

NSDictionary *DictionaryForNode(xmlNodePtr currentNode, NSMutableDictionary *parentResult,BOOL parentContent)

NSMutableDictionary *resultForNode = [NSMutableDictionary dictionary];
if (currentNode->name) 
    NSString *currentNodeContent = [NSString stringWithCString:(const char *)currentNode->name
                                                      encoding:NSUTF8StringEncoding];
    resultForNode[@"nodeName"] = currentNodeContent;


if (XML_ELEMENT_NODE != currentNode->type) 
    return nil;


xmlChar *nodeContent = xmlNodeGetContent(currentNode);

if (nodeContent != NULL) 
    NSString *currentNodeContent = [NSString stringWithCString:(const char *)nodeContent
                                                      encoding:NSUTF8StringEncoding];
    if ([resultForNode[@"nodeName"] isEqual:@"text"] && parentResult) 
        if (parentContent) 
            NSCharacterSet *charactersToTrim = [NSCharacterSet whitespaceAndNewlineCharacterSet];
            parentResult[@"nodeContent"] = [currentNodeContent stringByTrimmingCharactersInSet:charactersToTrim];
            xmlFree(nodeContent);
            return nil;
        
        if (currentNodeContent != nil) 
            resultForNode[@"nodeContent"] = currentNodeContent;
        
        return resultForNode;
     else 
        resultForNode[@"nodeContent"] = currentNodeContent;
    
    xmlFree(nodeContent);


xmlAttr *attribute = currentNode->properties;
if (attribute) 
    NSMutableArray *attributeArray = [NSMutableArray array];
    while (attribute) 
        NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary];
        NSString *attributeName = [NSString stringWithCString:(const char *)attribute->name
                                                   encoding:NSUTF8StringEncoding];
        if (attributeName) 
            attributeDictionary[@"attributeName"] = attributeName;
        

        if (attribute->children) 
            NSDictionary *childDictionary = DictionaryForNode(attribute->children, attributeDictionary, true);
            if (childDictionary) 
                attributeDictionary[@"attributeContent"] = childDictionary;
            
        

        if ([attributeDictionary count] > 0) 
            [attributeArray addObject:attributeDictionary];
        
        attribute = attribute->next;
    

    if ([attributeArray count] > 0) 
        resultForNode[@"nodeAttributeArray"] = attributeArray;
    


xmlNodePtr childNode = currentNode->children;
if (childNode) 
    NSMutableArray *childContentArray = [NSMutableArray array];
    while (childNode) 
        NSDictionary *childDictionary = DictionaryForNode(childNode, resultForNode,false);
        if (childDictionary) 
            [childContentArray addObject:childDictionary];
        
        childNode = childNode->next;
    
    if ([childContentArray count] > 0) 
        resultForNode[@"nodeChildArray"] = childContentArray;
    


xmlBufferPtr buffer = xmlBufferCreate();
xmlNodeDump(buffer, currentNode->doc, currentNode, 0, 0);
NSString *rawContent = [NSString stringWithCString:(const char *)buffer->content encoding:NSUTF8StringEncoding];
if (rawContent != nil) 
    resultForNode[@"raw"] = rawContent;

xmlBufferFree(buffer);
return resultForNode;

【讨论】:

【参考方案2】:

我解决了这个问题。当我的文档中有空标签时我得到了泄漏,我清楚地观察并修改了一些代码。基本上我在我的 XpathQuery.m 中纠正了。

NSArray *PerformXPathQuery(xmlDocPtr doc, NSString *query)

    xmlXPathContextPtr xpathCtx; 
    xmlXPathObjectPtr xpathObj;
    /* Create xpath evaluation context */
    xpathCtx = xmlXPathNewContext(doc);
    if(xpathCtx == NULL)
    
        return nil;
    
    /* Evaluate xpath expression */
    xpathObj = xmlXPathEvalExpression((xmlChar *)[query cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);
    if(xpathObj == NULL) 
        GLogInfo(@"%@",@"Unable to evaluate XPath");
        xmlXPathFreeObject(xpathObj);
        xmlXPathFreeContext(xpathCtx); 
        return nil;
    

    xmlNodeSetPtr nodes = xpathObj->nodesetval;
    if (!nodes)
    
        GLogInfo(@"%@",@"Nodes was nil.");
        xmlXPathFreeObject(xpathObj);
        xmlXPathFreeContext(xpathCtx); 
        return nil;
    

    NSStringEncoding encoding = cocoaEncodingFromXmlEncodingConst(doc->encoding);
    NSMutableArray *resultNodes = [NSMutableArray array];
    for (NSInteger i = 0; i < nodes->nodeNr; i++)
    
        NSDictionary *nodeDictionary = DictionaryForNode(nodes->nodeTab[i], nil, encoding);
        if (nodeDictionary)
        
            [resultNodes addObject:nodeDictionary];
        
    

    /* Cleanup */
    xmlXPathFreeObject(xpathObj);
    xmlXPathFreeContext(xpathCtx); 
    return resultNodes;

如果您使用相同的类,您绝对可以毫无疑问地使用此方法/考虑内存泄漏。祝你好运。

【讨论】:

真正的问题在于 xmlChar *nodeContent = xmlNodeGetContent(currentNode);【参考方案3】:

首先,如果内存是一个主要问题,那么使用 XML 无论如何都不是您的最佳解决方案。 JSON 或二进制格式的内存效率更高。

其次,您的跟踪不会显示框架中的泄漏。显示的是泄漏的对象,其内存由框架分配。实际泄漏更有可能在您的代码中,通常是通过从库中分配一个对象,但随后不释放(或在这种情况下释放)该对象。查看堆栈跟踪。

【讨论】:

以上是关于libxml2.2.dylib 造成大量内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Swift 重复 URLSession 造成大量内存泄漏

Android App解决卡顿慢之内存抖动及内存泄漏(发现和定位)

php执行shell命令,dyld:库未加载:/usr/lib/libxml2.2.dylib

Android性能优化之内存泄漏

内存优化:内存抖动和内存泄漏

python外篇(内存泄露)