Valgrind总结(1) —— 概述

一、前言:

对于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)


阅读更多
想对作者说点什么?
相关热词

博主推荐

换一批

没有更多推荐了,返回首页