【问题标题】:Can't detect huge memory usage in C program无法检测 C 程序中的大量内存使用情况
【发布时间】:2021-11-19 11:56:20
【问题描述】:

我在运行 C 程序时遇到大量内存使用情况。它使用的内存比预期的要多。由于大量内存使用,甚至操作系统有时也不得不终止进程(而且我的机器中有 20GB 的 RAM)。我尝试运行 valgrind 以查看是否有一些关于内存使用情况的线索。在 valgrind 输出中,我可以看到一个可能指向问题的警告:

==69541== Warning: set address range perms: large range [0x76eb040, 0x2cb27240) (undefined)

但是,我不知道如何知道这么大范围的内存分配在哪里。

希望这不是一个太笼统的问题。我试图提供解决问题的最少细节,但如果需要,我可以提供更多信息。

【问题讨论】:

  • 可能是内存泄漏。你在用malloc吗?还有任何递归函数调用或任何可能非常大的数组吗?
  • 是的,这是一个有很多内存分配的大项目。是否有可能检测到与这个大范围相关的malloc(s)?
  • Valgrind memcheck 应该能够检测内存泄漏。您需要确保用于存储指向使用 malloc 创建的对象的指针的任何变量在超出范围或重新分配之前使用 free 释放。
  • 感谢您的意见,我会回头看一下代码并尝试找到没有frees的mallocs。但是,有没有办法让 valgrind 或其他一些实用程序将我指向发生这种巨大内存分配的代码行?
  • 你需要一个好的静态分析工具。市场上有几种,但它们通常需要购买。 en.m.wikipedia.org/wiki/List_of_tools_for_static_code_analysis

标签: c memory valgrind


【解决方案1】:

我能够找到问题所在。我在这里发布我使用并为我工作的方法,以防它可能对其他人有用(尽管可能不是最整洁的方法)。

使用调试器,我发现这个地方正在发生巨大的分配(这需要很多时间)。然后我意识到我正在创建一个哈希表对象,它的大小作为参数传递。我没有传递参数,所以程序将一个垃圾(大)数字作为大小。

感谢所有分享您对我的问题的想法的人:)

【讨论】:

  • 如果你错误地调用了一个函数,你的编译器应该会警告你——但这假设你事先已经为它声明了原型——这也是值得做的事情。
【解决方案2】:

您应该使用带有 --leak-check=full 选项的 Valgrind 并使用 -g 选项编译代码

例子:

cat my_leak.c ; gcc -g my_leak.c ; valgrind --leak-check=full a.out
#include <malloc.h>

int main() {
    char* a = malloc(1000000);
    return 0;
}
==29805== Memcheck, a memory error detector
==29805== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29805== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==29805== Command: a.out
==29805== 
==29805== error calling PR_SET_PTRACER, vgdb might block
==29805== 
==29805== HEAP SUMMARY:
==29805==     in use at exit: 1,000,000 bytes in 1 blocks
==29805==   total heap usage: 1 allocs, 0 frees, 1,000,000 bytes allocated
==29805== 
==29805== 1,000,000 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29805==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==29805==    by 0x10915E: main (my_leak.c:4)
==29805== 
==29805== LEAK SUMMARY:
==29805==    definitely lost: 1,000,000 bytes in 1 blocks
==29805==    indirectly lost: 0 bytes in 0 blocks
==29805==      possibly lost: 0 bytes in 0 blocks
==29805==    still reachable: 0 bytes in 0 blocks
==29805==         suppressed: 0 bytes in 0 blocks
==29805== 
==29805== For lists of detected and suppressed errors, rerun with: -s
==29805== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Valgrind 版本:

valgrind --version
valgrind-3.15.0

【讨论】:

    【解决方案3】:

    每当 Valgrind 对大于 256Mbytes 的新内存范围设置权限时,都会生成您复制的消息。这么大的分配有点可疑,可能是内存大小计算错误。

    在您的情况下,分配是 625197568 字节(约 596Mbytes)。

    您可以使用massif 工具查看分配的位置(或非 Valgrind 工具,如 heaptrack)。

    【讨论】:

    • 使用massif(即运行valgrind --tool=masif)我无法收到之前收到的大分配警告。
    • 它运行完成了吗?如果是这样,您需要运行 ms_print(在 valgrind bin 目录中),或者,如果可以的话,运行一个单独的查看器,massif-visualizer。
    猜你喜欢
    • 1970-01-01
    • 2016-02-05
    • 2017-06-09
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    相关资源
    最近更新 更多