C++ C++;:使用std::map的微小内存泄漏

C++ C++;:使用std::map的微小内存泄漏,c++,memory,memory-leaks,C++,Memory,Memory Leaks,我正在编写一个定制的文本文件数据解析器(类似JSON),我花了很多时间试图找到其中的一个小内存泄漏 我正在使用VC++2008和命令_CrtMemCheckpoint和_crtdumpmomeryleaks检查内存泄漏 当我解析任何文件,然后将其从内存中删除(与任何其他已声明的内存一起),我会得到一个16字节的内存泄漏,如下所示: {290} normal block at 0x00486AF0, 16 bytes long. Data: < H `aH hH eH > C0

我正在编写一个定制的文本文件数据解析器(类似JSON),我花了很多时间试图找到其中的一个小内存泄漏

我正在使用VC++2008和命令_CrtMemCheckpoint和_crtdumpmomeryleaks检查内存泄漏

当我解析任何文件,然后将其从内存中删除(与任何其他已声明的内存一起),我会得到一个16字节的内存泄漏,如下所示:

{290} normal block at 0x00486AF0, 16 bytes long.
Data: <  H `aH  hH  eH > C0 9A 48 00 60 61 48 00 18 68 48 00 D8 65 48 00
classDefinitions是一个
std::map
并且是我的解析器类的私有成员

FastStr是一个简单的char*“包装器”,允许简单的c字符串作为键值;它没有内存泄漏(没有“新”命令)。'FSLClassDefinition*'显然是一个简单的类指针,所以这里也没有什么奇怪的

现在有一个问题:

  • 这一行在解析过程中执行了很多次,但我只得到一个16字节的块
  • 如果我解析另一个文件,就不会再有16字节的内存泄漏
  • 如果我将解析器从内存中删除(通过将它放在{}代码块中),然后在另一个代码块中重新创建它并让它解析另一个文件,那么我会得到一个16字节的内存泄漏
  • 这让我怀疑std::map中存在内存泄漏;但这也可能是我的错误。。。我很确定这是一条令人不快的线,因为如果我在它之前停止解析,就不会有内存泄漏;如果我在这一行之后停止解析,就会出现内存泄漏


    有人能对此发表评论吗?

    让我们排除一件事:
    std::map
    中没有漏洞。代码是每个开发人员都可以看到的,到现在它已经被捕获了


    如果你是正确的,我可以想象泄漏发生在复制
    classDef
    或匿名
    FastStr
    对象中。但是如果没有这两个方面的代码,就很难说了。你说它们都是指针,让我相信这句话只是一种症状,而不是真正的问题。显示一些代码怎么样?

    让我们排除一件事:
    std::map
    中没有泄漏。代码是每个开发人员都可以看到的,到现在它已经被捕获了


    如果你是正确的,我可以想象泄漏发生在复制
    classDef
    或匿名
    FastStr
    对象中。但是如果没有这两个方面的代码,就很难说了。你说它们都是指针,让我相信这句话只是一种症状,而不是真正的问题。显示一些代码怎么样?

    因为内存“泄漏”不会随着重复使用而扩展,它可能根本不是泄漏,而是由库分配的内存,直到内存分析完成后才会释放。内存通常由库分配,然后在后续调用中重用。因为库无法判断您的调用中的哪一个是最后一个,所以在您的程序退出或稍后退出之前,它不会释放它。

    因为内存“泄漏”不会随着重复使用而扩展,它可能根本不是泄漏,而是由库分配的内存,直到内存分析完成后才会释放。内存通常由库分配,然后在后续调用中重用。因为库无法判断您的哪个调用是最后一个调用,所以在您的程序退出或稍后退出之前,库不会释放它。

    我的直觉是查看FastStr。您说它是一个简单的char*包装器,但它如何处理被复制(即内部char*是被复制还是重新创建的)?请给我们看看FastStr的代码好吗

    除此之外,您列出的证据表明存在一些静态数据,或者如果您提到的“解析器”只在测试代码块中创建了一个,那么“解析器”对象的一个成员可能是内存泄漏的来源


    另一个建议是在更具描述性的工具(如valgrind)下运行代码以查明泄漏?Valgrind(或Purify)将告诉您代码中内存泄漏的精确位置。

    我的直觉是查看FastStr。您说它是一个简单的char*包装器,但它如何处理被复制(即内部char*是被复制还是重新创建的)?请给我们看看FastStr的代码好吗

    除此之外,您列出的证据表明存在一些静态数据,或者如果您提到的“解析器”只在测试代码块中创建了一个,那么“解析器”对象的一个成员可能是内存泄漏的来源


    另一个建议是在更具描述性的工具(如valgrind)下运行代码以查明泄漏?Valgrind(或Purify)将告诉您代码中内存泄漏的精确位置。

    到目前为止,我们还没有看到您的代码中的任何一行,因此我们几乎不可能说得更多,“在所有广泛使用的STL实现中,
    std::map
    在任何情况下都不会泄漏内存。”一旦映射的析构函数运行,它的所有内存都将被释放

    当然,如果您使用的是一些晦涩难懂的专有STL实现,那么一切都是错的,但除此之外,map并不是罪魁祸首

    当然,如果您确实怀疑
    map
    内存泄漏,请仔细检查。它是只包含头的代码,所以它是可见的,并且可以像调试自己的代码一样进行调试。在调试器中逐步检查它,查看它进行了哪些分配,以及它们是否再次被释放

    但更可能的问题是FastStr或。。。代码中还有其他内容

    尝试从代码中剥离尽可能多的内容,以获得再现错误的尽可能小的示例

    不要从一开始就运行完整的程序。如果您确定问题出在您发布的行中,那么您可以跳过所有初始解析,这将排除许多可能性。同样,也要删除之后发生的任何事情。如果这没有重现错误,那么问题就不在你所隔离的那条线上

    当你得到
    classDefinitions[FastStr(cString)] = classDef;
    
    return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty)));