【问题标题】:Valgrind understanding bytes allocated increase in heap summary?valgrind理解堆汇总中分配的字节数增加?
【发布时间】:2012-07-30 21:55:54
【问题描述】:

我一直在研究调试分叉 TCP 服务器中的内存使用情况。我认为我做得很好,我似乎无法在“堆摘要”中找到有关“分配的字节数”的信息。我的服务器运行时间越长,这个数字似乎就在不断增加:

==27526== 
==27526== HEAP SUMMARY:
==27526==     in use at exit: 0 bytes in 0 blocks
==27526==   total heap usage: 113 allocs, 113 frees, 283,043 bytes allocated
==27526== 
==27526== All heap blocks were freed -- no leaks are possible
==27526== 
==27526== For counts of detected and suppressed errors, rerun with: -v
==27526== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
==27528== 
==27528== HEAP SUMMARY:
==27528==     in use at exit: 0 bytes in 0 blocks
==27528==   total heap usage: 120 allocs, 120 frees, 300,808 bytes allocated
==27528== 
==27528== All heap blocks were freed -- no leaks are possible
==27528== 
==27528== For counts of detected and suppressed errors, rerun with: -v
==27528== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
==27537== 
==27537== HEAP SUMMARY:
==27537==     in use at exit: 0 bytes in 0 blocks
==27537==   total heap usage: 127 allocs, 127 frees, 318,573 bytes allocated
==27537== 
==27537== All heap blocks were freed -- no leaks are possible
==27537== 
==27537== For counts of detected and suppressed errors, rerun with: -v
==27537== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

虽然 Valgrind 报告 allocs 和 free 是相等的,并且没有泄漏是可能的,但我不相信分配的字节会增加。

那么:如果分配的字节数不断增加,这是否意味着即使 Valgrind 报告不可能发生泄漏,我也必须从某个堆中释放?

谢谢!

编辑: 有了 Gordon Bailey 的回答和其他提示,我仍然有点厌倦。写了这个小应用:

/* client.c */
#include <stdio.h>

void child_func(int childnum);

int main(int argc, char *argv[])
{
int nchildren = 1;
int pid;
int x;
if (argc > 1)
{
    nchildren = atoi(argv[1]);
}

for (x = 0; x < nchildren; x++)
{
    if ((pid = fork()) == 0)
    {
        child_func(x + 1);
        exit(0);
    }
}
wait(NULL);
return 0;
}

void child_func(int childnum)
{

int i;
for (i = 0; i < 1000; i++) {
            free(malloc(1));
    }
    sleep(1);
}

当我运行这个 Valgrind 输出是:

==28245== HEAP SUMMARY:
==28245==     in use at exit: 0 bytes in 0 blocks
==28245==   total heap usage: 1,000 allocs, 1,000 frees, 1,000 bytes allocated
==28245== 
==28245== All heap blocks were freed -- no leaks are possible
==28245== 
==28245== For counts of detected and suppressed errors, rerun with: -v
==28245== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
==28246== HEAP SUMMARY:
==28246==     in use at exit: 0 bytes in 0 blocks
==28246==   total heap usage: 1,000 allocs, 1,000 frees, 1,000 bytes allocated
==28246== 
==28246== All heap blocks were freed -- no leaks are possible

所以看起来堆上的所有内存都被清除了,并且与我的应用程序的输出肯定不同。

【问题讨论】:

  • 您的服务器中是否存在依赖于历史记录的内容?程序的输入是确定性的吗?如果是这样,如果你给它完全相同的输入会发生什么?请注意,输入还包含它打开的所有文件。
  • 不。服务器接受传入的连接,分叉自己来处理连接,解码数据并插入 Mysql 数据库。之后我退出分叉,不需要保留任何数据。我在 fork 上调用 exit,所以我认为它应该清除堆中的所有数据。
  • 看起来这只是 Valgrinds 在应用程序生命周期内报告总使用内存的方式(从下面的两个答案判断)。我不知道为什么我想知道这个,但这就是生活。
  • 嗯,你应该一定要留意它。 valgrind 不应该依赖于它自己之前的调用。如果你的程序真的在每次调用中不断增加约 7.8Kb,那么有一天它最终会耗尽内存。我的建议是编写一个持续执行此测试的脚本,grep total heap usage 行并将其放入文件中。在晚上运行脚本,早上你会看到一组漂亮的数字。如果有模式,你就有麻烦了。
  • 另外,valgrind(抑制:2 from 2)。您是否尝试过对于检测到和抑制的错误计数,重新运行:-v

标签: c valgrind


【解决方案1】:

Valgrind 的 bytes allocated 是您在进程运行时分配的总字节数。

如果你编译运行这个奇怪的小测试程序:

#include <stdio.h>
#include <stdlib.h>

int main()
{
   int i;

   for(i = 0; i < 1000; ++i){
      free(malloc(1));
   }

   return 0;
}

Valgrind 的输出是:

==2651== Memcheck, a memory error detector
==2651== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==2651== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2651== Command: ./test_prog
==2651==
==2651==
==2651== HEAP SUMMARY:
==2651==     in use at exit: 0 bytes in 0 blocks
==2651==   total heap usage: 1,000 allocs, 1,000 frees, 1,000 bytes allocated
==2651==
==2651== All heap blocks were freed -- no leaks are possible
==2651==
==2651== For counts of detected and suppressed errors, rerun with: -v
==2651== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)

现在真正的问题似乎是子进程如何影响这一点。

(编辑以确认我的想法)

【讨论】:

    【解决方案2】:

    它只是所有 malloc(和类似)调用的大小总和。如果你已经释放了它,valgrind 说你有,那就没问题了。即您的进程 27526 执行了 113 次分配,总共 283,043 个字节,

    如果您的服务器一直在分配内存,则该数字会上升,调用 free() 不会减少该数字。

    【讨论】:

      【解决方案3】:

      正如Godron所说,valgrind输出当前进程中的所有内存分配:

      toc@UnixServer:~$ valgrind --leak-check=full ./pb_valgrind
      ==11411== Memcheck, a memory error detector
      ==11411== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
      ==11411== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
      ==11411== Command: ./pb_valgrind
      ==11411== 
      ==11414== 
      ==11414== HEAP SUMMARY:
      ==11414==     in use at exit: 0 bytes in 0 blocks
      ==11414==   total heap usage: 1,000 allocs, 1,000 frees, 1,000 bytes allocated
      ==11414== 
      ==11414== All heap blocks were freed -- no leaks are possible
      ==11414== 
      ==11414== For counts of detected and suppressed errors, rerun with: -v
      ==11414== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
      ==11411== 
      ==11411== HEAP SUMMARY:
      ==11411==     in use at exit: 0 bytes in 0 blocks
      ==11411==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
      ==11411== 
      ==11411== All heap blocks were freed -- no leaks are possible
      ==11411== 
      ==11411== For counts of detected and suppressed errors, rerun with: -v
      ==11411== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
      

      在您的程序中,您执行 1000 个大小为 1 字节的 malloc,然后执行 1000 个空闲,这解释了输出。

      问候。

      【讨论】:

      • 您好 TOC,感谢您的帮助。问题是 Valgrind 在我的原始应用程序中报告了相同数量的分配和释放,但是分配的字节不断增加。
      • @lleto :差异运行之间有什么区别?如果你使用Linux,你需要知道子进程在fork之后继承了他父亲的所有内存(只读)在父亲内存空间中,当他想写这个内存时,内核会在子进程上创建一个新副本内存空间并使其可写(这就是我们所说的写时复制)。所以也许差异运行的环境不一样!
      • 当我在每个循环上运行应用程序时,我还有 6 个分配(和释放)。因此,每个循环中分配和释放的数量是相同的,但总体而言数量会增加。这会导致 Valgrind 正确(我相信)报告更多实际使用的堆内存。它在我的代码中,所以我需要从那里开始搜索...感谢您的帮助。
      • @lleto 好吧,有可能你在你的父母中分配内存,你的孩子释放了,但不是父母。因此,每次你 fork() 时,孩子都会有更多的内存(或更大的数组等),它会循环并释放。无论是那个还是你的每个孩子都只是有更多的工作要做,并使用更多的内存,然后释放,这没有真正的问题。'
      【解决方案4】:

      我认为问题在于,当我运行应用程序时,释放和分配的数量会增加每个循环。这导致分配的字节数变得更大,因为每次分配实际分配的内存更多,因为实际分配的内存更多。

      不知道为什么会这样,但它一定是我的错误代码,应该在另一个问题中。

      感谢您的帮助!

      【讨论】:

        猜你喜欢
        • 2014-10-06
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 2022-12-07
        • 2021-04-23
        • 2020-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多