7

我正在用 libxml2 编写一个 XML 解析器。实际上,我完成了它,但是有一个非常烦人的记忆问题。该程序首先从我的数据库中获取一些链接,所有这些链接都指向一个 XML 文件。我使用 curl 来下载它们。这个过程很简单:我下载一个文件,然后解析它,等等......

问题似乎出在解析完成时。Curl 下载下一个文件,但似乎之前的 XML 没有被释放,因为我猜 libxml2 会将它加载到 RAM 中。在解析最后一个 XML 时,我发现自己有大约 2.6GB 的泄漏(是的,其中一些文件真的很大......)而且我的机器只有 4GB 的 RAM。它暂时有效,但将来会向数据库添加更多链接,所以我现在必须修复它。

我的代码非常基本:

xmlDocPtr doc;
doc = xmlParseFile("data.xml");

/* code to parse the file... */

xmlFreeDoc(doc);

我尝试使用:

xmlCleanupParser();

但文档说:“它不会释放任何与文档相关的内存。” ( http://xmlsoft.org/html/libxml-parser.html#xmlCleanupParser )

所以,我的问题是:有人知道如何释放所有与文档相关的内存吗?

4

2 回答 2

6

问题是您以错误的方式查看统计数据...

当程序启动时,它会从操作系统为堆分配一些内存。当它执行malloc(或类似功能)时,C 运行时会从该堆中获取切片,直到它用完。之后,它会自动向操作系统请求更多内存,可能每次都以更大的块为单位。当程序执行此操作时free,它将释放的内存标记为可用于进一步malloc的 s,但它不会将内存返回给操作系统。

您可能认为这种行为是错误的,即程序正在泄漏,但事实并非如此:释放的内存被考虑在内,只是不在操作系统中,而是在应用程序的 C 库层中。对此的证明是,第二个 XML 文件的内存并没有添加到第一个文件中:只有当它是最大的文件时,它才会被注意到。

你也可能认为,如果这个内存不再被这个程序使用,它只是浪费在那里,不能用于其他进程。但这不是真的:如果内存在一段时间内没有被触及并且在其他地方需要它,操作系统虚拟内存管理器会将它换出并重用它。

所以,我的猜测是,实际上你没有问题。

PS:我刚才描述的并不总是正确的。特别是许多 C 库对大小内存块进行了区分,并以不同的方式分配它们。

于 2013-05-20T23:13:44.687 回答
1

游戏晚了,但今天才发现这个帖子。它也可能对其他读者有用。

如果您正在解析或生成大型文档,则可以考虑使用 XmlReader 和 XmlReader API。大大减少了内存使用量,无论输入有多大,实际上几乎是恒定的使用量。

http://xmlsoft.org/html/libxml-xmlreader.html http://xmlsoft.org/html/libxml-xmlwriter.html

于 2014-05-01T07:39:41.110 回答