[valgrind] 安装与使用
Date
:2022-07-28
Author
:AnimateX
01 下载 valgrind 稳定版源码
下载地址:Current Releases
,当前能选择的版本为 Valgrind 3.19.0
。
02 安装 valgrind
-
解压文件
tar -jxvf valgrind-3.19.0.tar.bz2
-
进入解压后的文件
cd valgrid-3.19.0
-
配置
./configure
-
编译
make
-
安装
make install
-
检查是否安装成功
valgrind --version
03 valgrind 使用手册
文档在线地址:manual
04 valgrind 工具套件说明
Memcheck
,Cachegrind
,Callgrind
,Massif
,helgrind
,DRD
,DHAT
,...
4-1 Memcheck
最常用工具,针对各种内存相关的
debug
问题
Memcheck detects memory-management problems, and is aimed primarily at C and C++ programs. When a program is run under Memcheck’s supervision, all reads and writes of memory are checked, and calls to malloc/new/free/delete are intercepted. As a result, Memcheck can detect if your program:
- Accesses memory it shouldn’t (areas not yet allocated, areas that have been freed, areas past the end of heap blocks, inaccessible areas of the stack).
- Uses uninitialised values in dangerous ways.
- Leaks memory.
- Does bad frees of heap blocks (double frees, mismatched frees).
- Passes overlapping source and destination memory blocks to memcpy() and related functions.
Memcheck reports these errors as soon as they occur, giving the source line number at which it occurred, and also a stack trace of the functions called to reach that line. Memcheck tracks addressability at the byte-level, and initialisation of values at the bit-level. As a result, it can detect the use of single uninitialised bits, and does not report spurious errors on bitfield operations. Memcheck runs programs about 10–30x slower than normal.
可以检测:内存越界、野指针、内存泄漏、多重释放、源被覆盖等问题。虽然跑的慢一点但是可以解决我的 lowB
代码能力。
4-2 Cachegrind
cachegrind
: 一个缓冲模拟器。它可以用来标出你的程序每一行执行的指令数和导致的缓冲不命中数。
Cachegrind is a cache profiler. It performs detailed simulation of the I1, D1 and L2 caches in your CPU and so can accurately pinpoint the sources of cache misses in your code. It identifies the number of cache misses, memory references and instructions executed for each line of source code, with per-function, per-module and whole-program summaries. It is useful with programs written in any language. Cachegrind runs programs about 20–100x slower than normal.
4-3 Callgrind
callgrind
在cachegrind
基础上添加调用追踪。它可以用来得到调用的次数以及每次函数调用的开销。作为对cachegrind
的补充,callgrind
可以分别标注各个线程,以及程序反汇编输出的每条指令的执行次数以及缓存未命中数。
Callgrind, by Josef Weidendorfer, is an extension to Cachegrind. It provides all the information that Cachegrind does, plus extra information about callgraphs. It was folded into the main Valgrind distribution in version 3.2.0. Available separately is an amazing visualisation tool, KCachegrind, which gives a much better overview of the data that Callgrind collects; it can also be used to visualise Cachegrind’s output.
4-4 Massif
massif
是一个堆剖析器,分析堆上的内存分配情况。
Massif is a heap profiler. It performs detailed heap profiling by taking regular snapshots of a program’s heap. It produces a graph showing heap usage over time, including information about which parts of the program are responsible for the most memory allocations. The graph is supplemented by a text or HTML file that includes more information for determining where the most memory is being allocated. Massif runs programs about 20x slower than normal.
4-5 Helgrind
Helgrind
线程调试器,能找到多线程程序中断数据竞争问题,不过这是一个实验性质的工具。
Helgrind is a thread debugger which finds data races in multithreaded programs. It looks for memory locations which are accessed by more than one (POSIX p-)thread, but for which no consistently used (pthread_mutex_) lock can be found. Such locations are indicative of missing synchronisation between threads, and could cause hard-to-find timing-dependent problems. It is useful for any program that uses pthreads. It is a somewhat experimental tool, so your feedback is especially welcome here.
4-6 DRD
DRD
是检测多线程C
和C ++
程序中错误的工具,对于锁的顺序异常(诸如:死锁)其分析需要更少的内存。
DRD is a tool for detecting errors in multithreaded C and C++ programs. The tool works for any program that uses the POSIX threading primitives or that uses threading concepts built on top of the POSIX threading primitives. While Helgrind can detect locking order violations, for most programs DRD needs less memory to perform its analysis.
4-7 Lackey, Nulgrind
一个示例程序,以其为模版可以创建你自己的工具。在程序结束后,它打印出一些基本的关于程序执行统计数据
Lackey and Nulgrind are also included in the Valgrind distribution. They don’t do very much, and are there for testing and demonstrative purposes.
4-8 DHAT
一个用于检查程序如何使用堆分配的工具,跟踪已分配的块,并检测内存访问可以查找哪些块。
DHAT is a tool for examining how programs use their heap allocations. It tracks the allocated blocks, and inspects every memory access to find which block, if any, it is to. It comes with a GUI to facilitate exploring the profile results.
05 代码初尝试
以下代码均使用 C11
测试。这里仅针对 memcheck
测试样例。
5-1 malloc/free 不匹配测试
#include <stdlib.h>
void func(void) {
int *ptr = malloc(10 * sizeof(int));
ptr[10] = 0;
}
int main()
{
func();
return 0;
}
编译测试:
clang -g memcheck_test.c -o test.out -Wall -O0 -std=c11
# gcc -g memcheck_test.c -o test.out -Wall -o0 -std=c11
valgrind --tool=memcheck --leak-check=yes ./test.out
valgrind
测试 log
:
==72931== Memcheck, a memory error detector
==72931== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==72931== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==72931== Command: ./test.out
==72931==
==72931== Invalid write of size 4
==72931== at 0x40114A: func (memcheck_test.c:5)
==72931== by 0x401173: main (memcheck_test.c:11)
==72931== Address 0x4a56068 is 0 bytes after a block of size 40 alloc'd
==72931== at 0x483C855: malloc (vg_replace_malloc.c:381)
==72931== by 0x401141: func (memcheck_test.c:4)
==72931== by 0x401173: main (memcheck_test.c:11)
==72931==
==72931==
==72931== HEAP SUMMARY:
==72931== in use at exit: 40 bytes in 1 blocks
==72931== total heap usage: 1 allocs, 0 frees, 40 bytes allocated # 问题说明:无free
==72931==
==72931== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==72931== at 0x483C855: malloc (vg_replace_malloc.c:381)
==72931== by 0x401141: func (memcheck_test.c:4)
==72931== by 0x401173: main (memcheck_test.c:11)
==72931==
==72931== LEAK SUMMARY:
==72931== definitely lost: 40 bytes in 1 blocks
==72931== indirectly lost: 0 bytes in 0 blocks
==72931== possibly lost: 0 bytes in 0 blocks
==72931== still reachable: 0 bytes in 0 blocks
==72931== suppressed: 0 bytes in 0 blocks
==72931==
==72931== For lists of detected and suppressed errors, rerun with: -s
==72931== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
可以发现 HEAP SUMMARY
提示:1 allocs, 0 frees, 40 bytes allocated
,对应前面无效的写入位置:
==72931== Invalid write of size 4
==72931== at 0x40114A: func (memcheck_test.c:5)
5-2 野指针测试
#include <stdio.h>
#include <stdlib.h>
void func2(void) {
int *ptr;
ptr[1] = 0;
}
int main()
{
func2();
return 0;
}
编译测试
clang -g memcheck_test.c -o test.out -Wall -O0 -std=c11
# gcc -g memcheck_test.c -o test.out -Wall -o0 -std=c11
valgrind --tool=memcheck --leak-check=yes ./test.out
测试结果
==74999== Memcheck, a memory error detector
==74999== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==74999== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==74999== Command: ./test.out
==74999==
==74999== Use of uninitialised value of size 8 # 定位问题 c:11 未初始化
==74999== at 0x40117C: func2 (memcheck_test.c:11)
==74999== by 0x4011C3: main (memcheck_test.c:19)
==74999==
==74999==
==74999== Process terminating with default action of signal 11 (SIGSEGV)
==74999== Bad permissions for mapped region at address 0x4011D4
==74999== at 0x40117C: func2 (memcheck_test.c:11)
==74999== by 0x4011C3: main (memcheck_test.c:19)
==74999==
==74999== HEAP SUMMARY:
==74999== in use at exit: 0 bytes in 0 blocks
==74999== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==74999==
==74999== All heap blocks were freed -- no leaks are possible
==74999==
==74999== Use --track-origins=yes to see where uninitialised values come from
==74999== For lists of detected and suppressed errors, rerun with: -s
==74999== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
5-3 内存越界测试
#include <stdio.h>
#include <stdlib.h>
void func(void) {
int *ptr = malloc(4 * sizeof(int));
// valid range is ptr[0]~ptr[3]
ptr[4] = 20;
free(ptr);
ptr = NULL;
}
int main()
{
func();
return 0;
}
编译测试
clang -g memcheck_test.c -o test.out -Wall -O0 -std=c11
# gcc -g memcheck_test.c -o test.out -Wall -o0 -std=c11
valgrind --tool=memcheck --leak-check=yes ./test.out
测试结果
==76067== Memcheck, a memory error detector
==76067== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==76067== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==76067== Command: ./test.out
==76067==
==76067== Invalid write of size 4 # 定位问题,无效写入
==76067== at 0x40115A: func (memcheck_test.c:7)
==76067== by 0x401193: main (memcheck_test.c:15)
==76067== Address 0x4a56050 is 0 bytes after a block of size 16 alloc'd
==76067== at 0x483C855: malloc (vg_replace_malloc.c:381)
==76067== by 0x401151: func (memcheck_test.c:5)
==76067== by 0x401193: main (memcheck_test.c:15)
==76067==
==76067==
==76067== HEAP SUMMARY:
==76067== in use at exit: 0 bytes in 0 blocks
==76067== total heap usage: 1 allocs, 1 frees, 16 bytes allocated
==76067==
==76067== All heap blocks were freed -- no leaks are possible
==76067==
==76067== For lists of detected and suppressed errors, rerun with: -s
==76067== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)