1

我有一个使用TinyXML加载的200 MB XML 文件。我的问题是当 TinyXML 对象被销毁时,它使用的内存将不会被重用。我用过在其他项目中使用过的内存泄漏检测器,并且手动单步执行了代码并没有发现任何内存泄漏,所以我不怀疑泄漏的内存是问题所在。

此代码将重现该问题:

#include <iostream>
#include <tinyxml.h>

int main()
{
    char* filename = "../LargeFile.xml";

    {
        TiXmlDocument targetDoc( filename );
        targetDoc.LoadFile();
    }

    char* buf = new char[ 524288000 ];
    delete [] buf;

    return 0;
}

使用地址空间监视器我可以看到,在LoadFile()有一大块红色之后,在targetDoc被破坏之后它都是黄色的。然后,当最终的 char buf 被分配时,它显示为红色,但在绿色空间的顶部,而不是从 TinyXML 中释放出来的黄色。如果尝试分配比绿色地址空间更多的缓冲区,应用程序将崩溃(内存不足)。这可以在下面的图片中看到。

加载后 卸载后 字符缓冲区分配

根据地址空间监视器页面“可用地址空间显示为绿色,保留地址显示为黄色,使用(提交的)内存区域显示为红色”那么为什么 TinyXML 释放的内存根据地址空间监视器保持“保留”状态。什么会导致这种情况发生,我该如何阻止它?

编辑:

“你在分配大缓冲区吗?如果是这样,那么黄色空间中可能存在内存碎片,并且没有地方可以分配大的连续缓冲区”

很好的问题,但这表明 TinyXML 存在内存泄漏,而我的工具都没有显示存在内存泄漏。

更新

我制作了无限分配整数的循环,最终似乎使用了所有黄色空间。但是较大的分配不使用它。这向我表明,在由 tinyXML 解析 xml 文件的过程中,堆中散落着一些小的泄漏,它以这样的方式对堆进行分段,使得只有小到足以容纳泄漏之间的对象才能在黄色空间中分配. 所以我在 TinyXML 中搜索了更长时间和更努力的漏洞,但仍然没有找到任何漏洞。一切似乎都得到了正确的释放,这让我回到了最初的困惑状态。

我无法解释这个问题。

字符缓冲区分配 字符缓冲区分配2 字符缓冲区分配3

4

2 回答 2

6

您是否真的看到任何其他内存问题的迹象?保留内存表示地址范围是从操作系统保留的,但实际上没有物理内存在使用。这没什么好担心的。当您下次需要内存时,它将首先来自该保留空间。

于 2011-03-23T01:39:50.360 回答
4

当 free() 完成时,大多数操作系统实际上并没有将内存释放回操作系统(Linux 有时会进行大量释放)。相反,应用程序使用 OS sbreak() 函数来增加内存,保持“高水位线”。只要您为每个 malloc() 执行 free(),内存就不会泄漏,未来的分配将来自同一内存。当然,可能是 TinyXML 内部的某些东西没有进行这种匹配,无论是有意还是无意,例如:

  • TinyXML 类中的某个函数或由它调用的函数可能有一个静态局部指针变量,该变量在首次调用该函数时被初始化为指向新分配的堆。如果在其他例程为更多临时数据分配大量内存之后发生这种情况,那么即使在释放后者内存之后,静态指针的分配也可能导致一些碎片,从而阻止在回收空间中分配巨大的连续块。
于 2011-03-23T01:42:44.053 回答