thk*_*ala 11
调试使用GCC编译的C代码时使用Valgrind的要点:
使用-O0编译代码.在一些相对罕见的情况下(例如内联汇编),您可能需要-O1.切勿使用更高的优化级别.编译器会破坏你的代码,使你的生活变得不可能.变量可以完全消失,函数可以在内联时神秘地消失,循环展开,等等.基本上除了-O0之外的其他任何东西都会冒可执行代码与源代码几乎没有相似之处的风险.
使用-g GCC选项将调试符号添加到代码中,并且不要删除可执行文件.与任何其他调试器非常相似,valgrind将使用可用的调试符号生成无限更有用的输出.他们将帮助valgrind匹配内存地址到代码中的特定文件和行号,这是非常宝贵的.
为了跟踪内存泄漏和许多其他问题,我建议您运行程序:
valgrind --log-file=valgrind.log --leak-check=full --track-origins=yes --show-reachable=yes ./program
Run Code Online (Sandbox Code Playgroud)
然后查看valgrind.log文件中发现的任何问题.
编辑:
关于我建议的valgrind选项:
--log-file =告诉valgrind将其输出发送到一个文件,我相信当你调试带有输出到控制台的程序时,或者发现很多问题时,这会使事情变得更容易.
--leak-check = full告诉valgrind告诉你每个泄漏的内存块的详细信息.
--track-originins = yes告诉valgrind找出未初始化值的来源.它与内存泄漏没有任何关系,尽管它可以帮助解决其他问题.但是,它会使您的程序变慢,因此您可能希望删除此选项并仅在跟踪未初始化的值时添加它.
--show-reachable = yes告诉valgrind输出已分配但未释放的内存块,即使在程序退出时仍有指向它们的指针.这些块在技术上不会丢失/泄露,因为您仍然有指向它们的指针.但是,它们可以a)指示程序中的逻辑问题(例如,无限增长的列表)b)如果main()在另一个更大的程序中作为函数集成,它们可能并且将成为内存泄漏.最好不要再留下这样的问题.
有一个--track-fds = yes选项可以帮助找到泄漏的文件描述符而不仅仅是内存.
一些程序员主张在程序结束时释放内存或关闭文件描述符,因为操作系统无论如何都会这样做.虽然是一个性能和代码大小优势在那里,恕我直言,这只能由有经验的程序员时进行,并且应该通过做去除说的产能释放的代码,而不是只是从来没有写它.否则,这会鼓励不允许的错误编码实践.
编辑2:
一个重要提示:如果valgrind指示代码中存在问题,那么即使程序没有崩溃,也很可能是正确的.根据结构对齐,内存分配器行为,平台,编译器版本和标志或月亮的相位,一些"次要"错误(例如,读取缓冲区末尾的一个字节)可能仍然是看不见的.如果您更改编译器,libc,平台或位数(例如,从64位到32位),具有此类问题的代码可能会中断.