【问题标题】:Valgrind claims there is unfreed memory. Is this bad?Valgrind 声称有未释放的内存。这很糟糕吗?
【发布时间】:2010-01-27 04:15:15
【问题描述】:

Valgrind 为我的代码提供了以下泄漏摘要。但是,我已经释放了所有 malloc 的内存。这是一件坏事,还是正常的?我的程序在 c 中。

==3513== 泄漏摘要:

==3513== 肯定丢失:0 个块中的 0 个字节。

==3513== 可能丢失:0 个块中的 0 个字节。

==3513== 仍可访问:1 个块中的 568 个字节。

==3513== 抑制:0 个块中的 0 个字节。

【问题讨论】:

  • 这些可能是libc中的全局变量,但是没有看到代码谁也说不出来。
  • 好吧,我有 99% 的把握我没有内存泄漏,除非我没有专门 malloc 的东西可能需要被释放。如果 libc 全局变量是一种明显的可能性,那么我会同意。
  • 这 568 个字节没有泄漏,但它们是从某个地方指向的,这可能意味着您冒着双重释放()等风险。
  • 我又检查了一些代码,发现问题在于我使用close()而不是fclose()来关闭文件。使用fclose() 后,still reachable 消失了。感谢您的所有帮助。
  • 使用 VLD 或 Deleaker 不用担心。

标签: c memory-leaks valgrind memcheck


【解决方案1】:

valgrind 消息still reachable: 568 bytes in 1 blocks. 表示在您的应用程序中释放了仍然“可访问”的内存,这意味着您在某处仍有指向它的指针。在关闭时,这可能意味着某种全局变量。但是,由于“肯定泄露”或“可能泄露”的字节数为零,因此这种情况完全是良性的。不用担心。

【讨论】:

  • 实际上是内存未释放仍然可以访问。但是,是的,它是良性的——因为你仍然有一个指向它的指针,原则上你仍然可以释放它(所以它不是真正的泄漏)。
【解决方案2】:

仍然可访问的内存意味着它被一个全局或静态指针指向。您要做的是使用--show-reachable=yes 运行 valgrind 以查看是否有问题。

通常它是无害的,并且来自这样的函数:

void foo()
{
    static char *buffer = 0;
    if (buffer == 0)
    {
        buffer = (char *)malloc(...);
    }
}

那个 malloc 仍然可以访问。但是无论调用多少次 foo ,你都会只分配一次缓冲区,所以在这里不释放它并没有什么坏处。

但是考虑这样的函数:

void foo()
{
    static node_t *head = 0;

    node_t *node = (node_t *)malloc(sizeof(node_t));
    if (node)
    {
        node->next = head;
        head = node;
    }
    ...
}

每次调用这个函数,都会分配另一个节点。虽然您可能只会在测试运行时泄漏几个节点,但在生产运行中,您可能会泄漏足够多的内存以致内存不足。

区分差异的一种方法是查看不同的运行是否总是泄漏相同的内存,或者泄漏更多的内存是具有更大输入的测试运行。

但同样,如果您想安全起见,请使用--show-reachable=yes 看看发生了什么。

【讨论】:

    【解决方案3】:

    这些没有泄露,也没有什么可担心的。内存可能是由 C 库分配的。如果您真的想知道它们被分配到哪里,请使用--leak-check=full --show-reachable=yes

    【讨论】:

      【解决方案4】:

      如果你确定你“已经释放了所有 malloc 的内存”,那么,没有任何问题。即使您可能经常需要解决这些问题,但您并不直接对来自其他方的组件中的内存泄漏负责。

      来自 valgrind 的报告并没有真正提供足够的信息让我们帮助您。

      我曾多次看到内存检查工具出现误报,但我对 valgrind 本身没有任何直接经验。

      【讨论】:

        【解决方案5】:

        它会给你块的地址吗?有时您可以通过查看这 568 个字节中的数据类型来了解很多。

        嗯,568 字节,大约是 MAX_PATH unicode 字符串的大小。

        【讨论】:

          【解决方案6】:

          将 free()'ed 的指针清零是个好主意,这会在(错误地)再次尝试取消引用它们时导致崩溃。

          【讨论】:

            【解决方案7】:

            就我个人而言,我总是忘记并检查valgrind make test,它总是添加至少几个额外的仍然可以访问的字节...确保您的应用程序直接由 valgrind 运行...:)

            【讨论】:

              猜你喜欢
              • 2011-10-10
              • 1970-01-01
              • 2017-09-14
              • 2013-12-23
              • 2010-10-05
              • 1970-01-01
              • 1970-01-01
              • 2012-12-03
              相关资源
              最近更新 更多