Libxml2.2.dylib creates many memory leaks

I am really having a hard time fixing / avoiding leaks when implementing the use of XpathQuery in my project. I am currently using libXml2.2.dylib for parsing. When I was checking for memory leaks with tools, I found many leaks in the framework.

libXml2.2.dylib leaks list

What would be the solution to avoid these leaks. Memory bothers us more. How can I fix / avoid these errors?

+3


source to share


3 answers


First, if memory is a serious issue, using XML is not your best solution. JSON or binary format is much more efficient.



Secondly, your footprint does not show leaks within the framework. What is showing are leaked objects whose memory has been allocated by the framework. Most likely an actual leak in your code, usually by allocating an object from the library, but then not freeing (or freeing in this case) the object. Take a look at the stack traces.

+3


source


I solved the problem. I got leaks when I have empty tags in my documents that I have clearly observed and modified some code. This fix me in my 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;
}

      



If you are using the same class, you can use this method absolutely without any hesitation / thought of a memory leak. Good luck.

+2


source


if you are using TFHpple then you need to add the following code to

DictionaryForNode

method

XPathQuery class

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

      

So your final method should look like

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;
}

      

0


source







All Articles