【问题标题】:how to find allocated memory in linux如何在linux中找到分配的内存
【发布时间】:2010-11-18 10:21:34
【问题描述】:

大家下午好,

我想要完成的工作:我想实现一个 C++ 单元测试夹具的扩展,以检测测试是否分配了内存并且不释放它。我的想法是在测试前后记录分配级别或空闲内存级别。如果它们不匹配,那么您就是在泄漏内存。

到目前为止我所做的尝试:我编写了一个例程来读取 /proc/self/stat 以获取 vm 大小和驻留集大小。居民集大小似乎是我需要的,但显然不正确。它在没有内存分配的连续调用函数之间发生变化。我相信它返回的是使用的缓存内存,而不是分配的内存。它还以 4k 为增量变化,因此太粗糙而无法真正使用。

我可以通过分配一个本地并保存它的地址来获得堆栈大小。这样做有什么问题吗?

有没有办法在 linux 上获得真正的空闲或分配的内存?

谢谢

【问题讨论】:

  • 它以 4k 为增量变化,因为这是 Linux 上的默认页面大小。内存是按页分配给进程的,而不是逐字节分配的,因此,如果您谈论的是进程的总体内存消耗,那么这并不是粗粒度的,而是真正发生的事情。
  • 如果它显示我使用了 4k 页的内存并且我泄漏了 100 个字节,我可能不会看到我正在使用的 4k 页的数量有任何变化。这就是为什么我说这个应用程序的粒度太粗了
  • 在应用程序退出之前,内存可能永远不会返回到操作系统,因此检查内存使用量不是一个可行的测试。注意:应用程序接收 4K 块的内存,然后管理该页面,直到它退出。内存可能会被多次分配和释放,而无需返回操作系统。
  • @Jay 如果泄漏的 100 字节导致您的进程保留一个内存页面,否则它会返回给操作系统,那么可以说您的程序泄漏了 4k 页面。跨度>
  • 我想你错过了这个主意。如果它以整数 4k 增量显示已用内存,并且我的泄漏将单元测试程序使用的总内存从 10 页更改为 10.01 页,则两者都将以整数 10 报告给我。泄漏将无法检测到,因为四舍五入。

标签: c++ linux unit-testing


【解决方案1】:

您最好的选择实际上可能是使用专门为查找内存泄漏而设计的工具。我有使用Electric Fence 的个人经验,它易于使用并且似乎可以很好地完成工作(不确定它处理C++ 的效果如何)。其他人也推荐Dmalloc

当然,每个人似乎都喜欢Valgrind,它几乎可以做任何事情,甚至还有前端(尽管任何有前端构建的东西都意味着它可能不是最简单的东西)世界)。如果KDE 的人可以推荐它,它必须能够处理任何事情。 (我并不是说 KDE 有什么不好,只是因为它是一个非常大的 C++ 代码库,所以如果 Valgrind 可以处理 KDE 软件,它一定有它的优势。虽然我没有作为 Electric Fence 的个人经验对我来说总是足够的)

【讨论】:

  • 我必须为此推荐 Valgrind。这是一个非常强大的工具并且相对容易使用。为了发现泄漏,您只需运行“valgrind --tool=memcheck --leak-check=full ./TestProgram args”并阅读报告。
  • 我同意 - 让您的单元测试脚本在 valgrind 下运行程序并解析 valgrind 报告以查找内存泄漏 - 作为奖励,您还会发现其他内存错误,例如双释放和无效使用已释放的块。
  • 我肯定会将此添加到测试方案中。谢谢推荐
【解决方案2】:

我不得不同意 Valgrind 和类似的建议,但如果运行时开销太大,一种选择可能是使用 mallinfo() 调用来检索当前分配内存的统计信息,并检查 @987654322 是否@ 非零。

请注意,这必须在调用全局析构函数之前运行 - 因此,如果您在那里清理了任何分配,这将记录一个误报。它也不会告诉您分配的位置在哪里 - 但这是确定哪些测试用例需要工作的良好第一步。

【讨论】:

  • 这很简单,重量轻,速度快。使用 gnu 编译器时,它可以完成 new 和 malloc 的工作。它是快速指出需要注意的代码的好方法。我确信在 valgrind 的帮助下,它会让我的代码变得更好。赞一个!
  • @Jay 它是否也考虑了所有类型的分配(STL 和对象的特定 new/delete 运算符)?
  • @GuyAvraham 据我所知,C++、STL 和 new/delete 都使用操作系统调用的标准分配方法。如果没有广泛的研究,我猜会是这样。
【解决方案3】:

不要查看操作系统来获取分配信息。 C 库在内部管理内存,并且只要求操作系统以块的形式提供更多 RAM(在您的情况下为 4KB)。在大多数情况下,它从未发布回操作系统,因此您无法真正检查那里的任何内容。

您必须修补 malloc()free() 才能获得所需的信息。

或者,使用 Valgrind。

【讨论】:

    【解决方案4】:

    不是直接的答案,但您可以重新定义 ::new 和 ::delete 运算符,并在内部通过单例或全局对象跟踪已分配和取消分配的内存。

    编辑:如果这是一个个人的 DIY 项目,那就太棒了。但是,如果它对于某些关键的事情,您总是可以跳到可用的众多泄漏检测库/程序之一,快速谷歌搜索就足够了。

    【讨论】:

    • 我曾希望有一个轻量级的简单答案。我想让单元测试简单快速。如果我找不到更容易的东西,Valgrind 看起来还不错。谢谢
    【解决方案5】:

    google-perftools 可以在您的测试代码中使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-24
      • 2014-04-20
      • 1970-01-01
      • 2017-07-03
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多