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 造成大量内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章
Android App解决卡顿慢之内存抖动及内存泄漏(发现和定位)