最终审判

既然修改了代码,再用valgrind运行一次:

最终审判 - 图1

泄漏已修复

你运行了和刚刚一样的测试数据,但这次程序清理了堆上的所有东西。

你破案了吗?即使这次没能发现泄漏并修复它也不用担心,存储器泄漏是C程序中最难发现的错误。事实上,现在你用的很多C程序都隐藏着一些存储器错误,所以valgrind工具就非常有用。

  • 发现泄漏。

  • 定位泄漏。

  • 检验泄漏是否修复。

这里没有蠢问题

问:valgrind说泄漏的存储器是在第46行创建的,但我们却修改了另一行代码,为什么?

:虽然数据“Loretta…”是由第46行代码放到堆上的,但泄漏却发生在变量(current->question)重新赋值的那一刻,因为当时变量指向的“Loretta…”还没有释放。创建数据不会发生泄漏,只有当程序失去了所有对数据的引用才会导致泄漏。

问:我的Mac/Windows/FreeBSD系统可以安装valgrind吗?

:在http://valgrind.org上可以查看valgrind最新发行版的详细信息。

问:那么valgrind是怎么拦截malloc()free()的?

malloc()free()包含在C标准库中,而valgrind有一个库,里面有它自己的malloc()free()。当用valgrind运行程序时,程序会使用valgrind的函数,而不是C标准库中的函数。

问:为什么编译器在编译代码时不默认包含调试信息?

:因为调试信息会使可执行文件变大,同时也可能让程序变得更慢。

问:valgrind这个名字的由来是什么?

:valgrind是英灵殿1入口的名字,而valgrind(程序)为你打开了一扇通向计算机堆的大门。

1 北欧神话中,死亡之神奥丁用来款待阵亡将士英灵的殿堂。——译者注

 

最终审判 - 图2要点

  • valgrind可以检查存储器泄漏。

  • valgrind通过拦截对malloc()free()的调用来工作。

  • 程序在停止运行时,valgrind会打印留在堆上数据的详细信息。

  • 编译代码时,如果在可执行文件中加上调试信息,valgrind可以提供更多信息。

  • 多次运行程序可以缩小泄漏的范围。

  • valgrind可以告诉你源文件的哪行代码把数据放到了堆上。

  • valgrind可以用来检验泄漏是否已修复。