Valgrind总结(1) —— 概述
2017-05-20 22:18
309 查看
一、前言:
对于Linux开发,valgrind的重要性是不言而喻的。尤其在memory error、memory leak的问题定位和排查方面,发挥着极其重要的作用。
记得刚毕业那会儿,当年的部门领导曾经无数次强调valgrind重要性。曾经在开发过程中,虽然也有使用valgrind,但是从来没有对valgrind这个工具做过完整总结。
近期决定对valgrind做一个总结,也算是偿还以前欠下的债吧。
二、概述:
1. 关于编译选项:
针对memcheck工具,需要注意以下几点:
a. 强烈推荐被调试的目标程序在编译时加入-g参数,这样再运行valgrind memcheck时,可以拿到更为丰富的调试信息,比如行号,调用栈等。
b. 当使用-O0编译目标程序时,valgrind可以保证输出的所有警告、错误提示信息都是准确的,副作用是程序运行会非常慢。
c. 当使用-O1编译目标程序时,valgrind可以保证程序运行速度相对较快,副作用是无法保证错误提示信息100%精确,比如,行号会不精确。(这点也很好理解,因为-O1下编译器会对指令进行重排)
d. valgrind不推荐使用-O2和-O3编译目标程序,此时错误提示信息可能会存在误报,比如,valgrind会报大量uninitialised-value错误,实际这些错误并不真实存在。
e. 在编译目标程序时添加-fno-inline,有利于valgrind生成更为精确的堆栈信息。(非必需)
注意:如果不添加-fno-inline选项,也可以在运行valgrind时添加--read-inline-info=yes,这样valgrind会读取目标程序调试信息,使函数调用链能够正确显示。
f. 在编译目标程序时推荐使用-Wall,打印所有编译器告警信息。因为在较高的编译优化级别下,valgrind可能无法检测出全部编译期告警信息。
其他用于profile相关的工具,比如Cachegrind,通常不受编译优化选项的影响。在测试前,往往需要让程序在正常的编译优化选项下进行编译(比如-O2/-O3),之后再运行valgrind。
2. 关于输出信息:
为了说明valgrind的基本使用,以下是一个简单的示例(来自valgrind官网)。
当运行valgrind时,程序会输出以下信息:
关于上面这个例子,有几点是值得关注的:
a) valgrind实际上提供了一组默认工具集。如果不指定具体运行哪个工具集,则默认运行memcheck。
在上面的示例中,valgrind demo 实际等价于 valgrind --tool=memcheck demo。
b) 最左侧的数字 ——17084,实是PID。
c) Invalid write of size 4
说明了具体的错误类型,说明发生了写越界。
由于目标程序采用-O0进行编译,可以看到出现错误时完整的堆栈信息。
d) definitely lost: 40 bytes in 1 blocks
上述信息说明代码中存在明确的内存泄漏。
如果在运行时添加了--leak-check=full,则会输出以下信息:
对于Linux开发,valgrind的重要性是不言而喻的。尤其在memory error、memory leak的问题定位和排查方面,发挥着极其重要的作用。
记得刚毕业那会儿,当年的部门领导曾经无数次强调valgrind重要性。曾经在开发过程中,虽然也有使用valgrind,但是从来没有对valgrind这个工具做过完整总结。
近期决定对valgrind做一个总结,也算是偿还以前欠下的债吧。
二、概述:
1. 关于编译选项:
针对memcheck工具,需要注意以下几点:
a. 强烈推荐被调试的目标程序在编译时加入-g参数,这样再运行valgrind memcheck时,可以拿到更为丰富的调试信息,比如行号,调用栈等。
b. 当使用-O0编译目标程序时,valgrind可以保证输出的所有警告、错误提示信息都是准确的,副作用是程序运行会非常慢。
c. 当使用-O1编译目标程序时,valgrind可以保证程序运行速度相对较快,副作用是无法保证错误提示信息100%精确,比如,行号会不精确。(这点也很好理解,因为-O1下编译器会对指令进行重排)
d. valgrind不推荐使用-O2和-O3编译目标程序,此时错误提示信息可能会存在误报,比如,valgrind会报大量uninitialised-value错误,实际这些错误并不真实存在。
e. 在编译目标程序时添加-fno-inline,有利于valgrind生成更为精确的堆栈信息。(非必需)
注意:如果不添加-fno-inline选项,也可以在运行valgrind时添加--read-inline-info=yes,这样valgrind会读取目标程序调试信息,使函数调用链能够正确显示。
f. 在编译目标程序时推荐使用-Wall,打印所有编译器告警信息。因为在较高的编译优化级别下,valgrind可能无法检测出全部编译期告警信息。
其他用于profile相关的工具,比如Cachegrind,通常不受编译优化选项的影响。在测试前,往往需要让程序在正常的编译优化选项下进行编译(比如-O2/-O3),之后再运行valgrind。
2. 关于输出信息:
为了说明valgrind的基本使用,以下是一个简单的示例(来自valgrind官网)。
#include <stdlib.h> void f(void) { int* x = malloc(10 * sizeof(int)); x[10] = 0; // problem 1: heap block overrun } // problem 2: memory leak -- x not freed int main(void) { f(); return 0; }
当运行valgrind时,程序会输出以下信息:
[adam040606@localhost test01]$ valgrind demo ==17084== Memcheck, a memory error detector ==17084== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==17084== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info ==17084== Command: demo ==17084== ==17084== Invalid write of size 4 ==17084== at 0x40054E: f (in /home/adam040606/Projects/valgrindTests/test01/demo) ==17084== by 0x40055E: main (in /home/adam040606/Projects/valgrindTests/test01/demo) ==17084== Address 0x51f7068 is 0 bytes after a block of size 40 alloc'd ==17084== at 0x4C29BE3: malloc (vg_replace_malloc.c:299) ==17084== by 0x400541: f (in /home/adam040606/Projects/valgrindTests/test01/demo) ==17084== by 0x40055E: main (in /home/adam040606/Projects/valgrindTests/test01/demo) ==17084== ==17084== ==17084== HEAP SUMMARY: ==17084== in use at exit: 40 bytes in 1 blocks ==17084== total heap usage: 1 allocs, 0 frees, 40 bytes allocated ==17084== ==17084== LEAK SUMMARY: ==17084== definitely lost: 40 bytes in 1 blocks ==17084== indirectly lost: 0 bytes in 0 blocks ==17084== possibly lost: 0 bytes in 0 blocks ==17084== still reachable: 0 bytes in 0 blocks ==17084== suppressed: 0 bytes in 0 blocks ==17084== Rerun with --leak-check=full to see details of leaked memory ==17084== ==17084== For counts of detected and suppressed errors, rerun with: -v ==17084== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
关于上面这个例子,有几点是值得关注的:
a) valgrind实际上提供了一组默认工具集。如果不指定具体运行哪个工具集,则默认运行memcheck。
在上面的示例中,valgrind demo 实际等价于 valgrind --tool=memcheck demo。
b) 最左侧的数字 ——17084,实是PID。
c) Invalid write of size 4
说明了具体的错误类型,说明发生了写越界。
由于目标程序采用-O0进行编译,可以看到出现错误时完整的堆栈信息。
d) definitely lost: 40 bytes in 1 blocks
上述信息说明代码中存在明确的内存泄漏。
如果在运行时添加了--leak-check=full,则会输出以下信息:
==17543== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==17543== at 0x4C29BE3: malloc (vg_replace_malloc.c:299) ==17543== by 0x400541: f (in /home/adam040606/Projects/valgrindTests/test01/demo) ==17543== by 0x40055E: main (in /home/adam040606/Projects/valgrindTests/test01/demo)
相关文章推荐
- Reporting Services总结、概述
- JIURL PE 格式学习总结(一)-- PE文件概述
- 总结:SharePoint Designer 2010 DVWP (1) -- 概述 -- XsltListViewWebPart和DataFormWebPart
- oracle概述与总结1
- JavaScript学习总结_一.概述
- oracle概述与总结2
- XXX平台音频概述和loudspeaker调试总结
- ajax概述与总结
- oracle概述与总结1
- RFID会议签到系统总结(二)-- 功能概述
- 游戏概述-总结
- Entity Framework 学习总结之一:ADO.NET 实体框架概述
- vmware经验总结--1.vmware概述(好文章收藏了哈!)
- RFID会议签到系统总结(三)-- 模块概述(上)
- RFID会议签到系统总结(十三)――模块概述(下)
- vmware经验总结--1.vmware概述
- J2SE个人总结2-JAVA概述
- Entity Framework 学习总结之一:ADO.NET 实体框架概述
- 计算机技术概述(总结)