用valgrind检查内存问题
Valgrind
Valgrind作为一个免费且优秀的工具包,平时大部分人可能都是使用valgrind检测内存问题,如内存泄露,越界等。
Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。下面分别介绍个工具的作用:
Memcheck
-
使用未初始化的内存 (Use of uninitialised memory)
-
使用已经释放了的内存 (Reading/writing memory after it has been free’d)
-
使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
-
对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
-
申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
-
malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
-
src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions
Callgrind
Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
Cachegrind
它模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
Helgrind
它主要用来检查多线程程序中出现的竞争问题。Helgrind 寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为” Eraser” 的竞争检测算法,并做了进一步改进,减少了报告错误的次数。
Massif
堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。
Valgrind使用举例
example.c
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int main() 5 { 6 int a[100]; //4*100=400bytes,stack 7 int *b = malloc(sizeof(int) * 100); //4*100=400bytes,heap 有错误,没有释放内存 8 9 return 0; 10 }
安装及使用(Ubuntu16.04)
1 1/*安装Valgrind*/ 2 sudo apt install valgrind 3 2/*编译源程序*/ 4 gcc example.c -o example 5 6 3/*输入valgrind的有关命令*/ 7 /*默认为tool=memcheck*/ 8 valgrind ./example 9 10 ==3130== Memcheck, a memory error detector 11 ==3130== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 12 ==3130== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 13 ==3130== Command: ./example 14 ==3130== 15 ==3130== 16 ==3130== HEAP SUMMARY: 17 ==3130== in use at exit: 400 bytes in 1 blocks 18 ==3130== total heap usage: 1 allocs, 0 frees, 400 bytes allocated 19 ==3130== 20 ==3130== LEAK SUMMARY: 21 ==3130== definitely lost: 400 bytes in 1 blocks 22 ==3130== indirectly lost: 0 bytes in 0 blocks 23 ==3130== possibly lost: 0 bytes in 0 blocks 24 ==3130== still reachable: 0 bytes in 0 blocks 25 ==3130== suppressed: 0 bytes in 0 blocks 26 ==3130== Rerun with --leak-check=full to see details of leaked memory 27 ==3130== 28 ==3130== For counts of detected and suppressed errors, rerun with: -v 29 ==3130== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 30 31 32 /*--leak-check=full可以看内存泄漏的细节*/ 33 valgrind --tool=memcheck --leak-check=full ./example 34 35 ==3152== Memcheck, a memory error detector 36 ==3152== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 37 ==3152== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 38 ==3152== Command: ./example 39 ==3152== 40 ==3152== 41 ==3152== HEAP SUMMARY: 42 ==3152== in use at exit: 400 bytes in 1 blocks 43 ==3152== total heap usage: 1 allocs, 0 frees, 400 bytes allocated 44 ==3152== 45 ==3152== 400 bytes in 1 blocks are definitely lost in loss record 1 of 1 //显示了malloc分配的内存泄露 46 ==3152== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 47 ==3152== by 0x4005B9: main (in /home/rogn/Desktop/MyCode/example) 48 ==3152== 49 ==3152== LEAK SUMMARY: 50 ==3152== definitely lost: 400 bytes in 1 blocks 51 ==3152== indirectly lost: 0 bytes in 0 blocks 52 ==3152== possibly lost: 0 bytes in 0 blocks 53 ==3152== still reachable: 0 bytes in 0 blocks 54 ==3152== suppressed: 0 bytes in 0 blocks 55 ==3152== 56 ==3152== For counts of detected and suppressed errors, rerun with: -v 57 58 59 /*上面只能看到堆内存*/ 60 /*使用--tool=massif查看堆栈内存*/ 61 rogn@ubuntu:~/Desktop/MyCode$ valgrind --tool=massif ./example 62 ==3160== Massif, a heap profiler 63 ==3160== Copyright (C) 2003-2015, and GNU GPL'd, by Nicholas Nethercote 64 ==3160== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 65 ==3160== Command: ./example 66 ==3160== 67 ==3160== 68 rogn@ubuntu:~/Desktop/MyCode$ ls 69 example example.c massif.out.3160 70 rogn@ubuntu:~/Desktop/MyCode$ ms_print massif.out.3160 71 -------------------------------------------------------------------------------- 72 Command: ./example 73 Massif arguments: (none) 74 ms_print arguments: massif.out.3160 75 -------------------------------------------------------------------------------- 76 77 78 B 79 408^ : 80 | : 81 | : 82 | : 83 | : 84 | : 85 | : 86 | : 87 | : 88 | : 89 | : 90 | : 91 | : 92 | : 93 | : 94 | : 95 | : 96 | : 97 | : 98 | : 99 0 +----------------------------------------------------------------------->ki 100 0 102.0 101 102 Number of snapshots: 2 103 Detailed snapshots: [] 104 105 -------------------------------------------------------------------------------- 106 n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) 107 -------------------------------------------------------------------------------- 108 0 0 0 0 0 0 109 1 104,414 408 400 8 0 110 111 /*查看整个程序使用的内存和时间*/ 112 rogn@ubuntu:~/Desktop/MyCode$ valgrind --tool=massif --pages-as-heap=yes ./example 113 ==3191== Massif, a heap profiler 114 ==3191== Copyright (C) 2003-2015, and GNU GPL'd, by Nicholas Nethercote 115 ==3191== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 116 ==3191== Command: ./example 117 ==3191== 118 ==3191== 119 rogn@ubuntu:~/Desktop/MyCode$ ls //查看当前目录下的文件,发现多了一个名叫massif.out.3191的文件(3191其实就是PID) 120 example example.c massif.out.3160 massif.out.3191 121 rogn@ubuntu:~/Desktop/MyCode$ ms_print massif.out.3191 //使用ms_print程序打印出massif.out.391 122 -------------------------------------------------------------------------------- 123 Command: ./example 124 Massif arguments: --pages-as-heap=yes 125 ms_print arguments: massif.out.3191 126 -------------------------------------------------------------------------------- 127 128 129 MB 130 6.172^ //这个就是总的内存了,所谓的Memory limit就是指这个 : 131 | ::@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#::::::::::::::::::::::::::::: 132 | : @ # : 133 | : @ # : 134 | : @ # : 135 | : @ # : 136 | : @ # : 137 | : @ # : 138 | : @ # : 139 | : @ # : 140 | : @ # : 141 | : @ # : 142 | : @ # : 143 | :::: @ # : 144 | :::: @ # : 145 | :::: @ # : 146 | :::: @ # : 147 | :::: @ # : 148 | :::: @ # : 149 | :::: @ # : 150 0 +----------------------------------------------------------------------->ki 151 0 148.4 //运行时间,单位是ms 152 153 Number of snapshots: 24 154 Detailed snapshots: [9, 10, 20, 21 (peak)] 155 156 -------------------------------------------------------------------------------- 157 n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) 158 -------------------------------------------------------------------------------- 159 0 0 4,096 4,096 0 0 160 1 0 12,288 12,288 0 0 161 2 0 167,936 167,936 0 0 162 3 0 176,128 176,128 0 0 163 4 0 180,224 180,224 0 0 164 5 0 184,320 184,320 0 0 165 6 0 188,416 188,416 0 0 166 7 0 196,608 196,608 0 0 167 8 0 200,704 200,704 0 0 168 9 0 204,800 204,800 0 0 169 100.00% (204,800B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc. 170 ->98.00% (200,704B) 0xFFFFFFFFFFFFFFFF: ??? 171 | 172 ->02.00% (4,096B) 0x4000C2F: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 173 174 -------------------------------------------------------------------------------- 175 n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) 176 -------------------------------------------------------------------------------- 177 10 0 204,800 204,800 0 0 178 100.00% (204,800B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc. 179 ->98.00% (200,704B) 0xFFFFFFFFFFFFFFFF: ??? 180 | 181 ->02.00% (4,096B) 0x4000C2F: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 182 183 -------------------------------------------------------------------------------- 184 n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) 185 -------------------------------------------------------------------------------- 186 11 0 200,704 200,704 0 0 187 12 0 200,704 200,704 0 0 188 13 6,945 2,306,048 2,306,048 0 0 189 14 7,057 2,314,240 2,314,240 0 0 190 15 10,328 2,400,256 2,400,256 0 0 191 16 12,391 2,404,352 2,404,352 0 0 192 17 13,061 6,377,472 6,377,472 0 0 193 18 13,153 6,402,048 6,402,048 0 0 194 19 13,500 6,418,432 6,418,432 0 0 195 20 18,839 6,422,528 6,422,528 0 0 196 100.00% (6,422,528B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc. 197 ->96.88% (6,221,824B) 0x401B4B9: mmap (mmap.c:34) 198 | ->94.64% (6,078,464B) 0x40068CB: _dl_map_object_from_fd (dl-map-segments.h:56) 199 | | ->94.64% (6,078,464B) 0x4008C25: _dl_map_object (dl-load.c:2498) 200 | | ->61.86% (3,973,120B) 0x400DBA0: openaux (dl-deps.c:63) 201 | | | ->61.86% (3,973,120B) 0x4010562: _dl_catch_error (dl-error.c:187) 202 | | | ->61.86% (3,973,120B) 0x400E1E0: _dl_map_object_deps (dl-deps.c:254) 203 | | | ->61.86% (3,973,120B) 0x4003A27: dl_main (rtld.c:1647) 204 | | | ->61.86% (3,973,120B) 0x4019630: _dl_sysdep_start (dl-sysdep.c:249) 205 | | | ->61.86% (3,973,120B) 0x4001C28: _dl_start (rtld.c:323) 206 | | | ->61.86% (3,973,120B) 0x4000C36: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 207 | | | 208 | | ->32.78% (2,105,344B) 0x4000EB3: map_doit (rtld.c:499) 209 | | ->32.78% (2,105,344B) 0x4010562: _dl_catch_error (dl-error.c:187) 210 | | ->32.78% (2,105,344B) 0x40020D4: handle_ld_preload (rtld.c:682) 211 | | ->32.78% (2,105,344B) 0x40039AD: dl_main (rtld.c:1539) 212 | | ->32.78% (2,105,344B) 0x4019630: _dl_sysdep_start (dl-sysdep.c:249) 213 | | ->32.78% (2,105,344B) 0x4001C28: _dl_start (rtld.c:323) 214 | | ->32.78% (2,105,344B) 0x4000C36: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 215 | | 216 | ->01.34% (86,016B) 0x4011773: _dl_sysdep_read_whole_file (dl-misc.c:62) 217 | | ->01.34% (86,016B) 0x4018506: _dl_load_cache_lookup (dl-cache.c:199) 218 | | ->01.34% (86,016B) 0x4009167: _dl_map_object (dl-load.c:2364) 219 | | ->01.34% (86,016B) 0x400DBA0: openaux (dl-deps.c:63) 220 | | ->01.34% (86,016B) 0x4010562: _dl_catch_error (dl-error.c:187) 221 | | ->01.34% (86,016B) 0x400E1E0: _dl_map_object_deps (dl-deps.c:254) 222 | | ->01.34% (86,016B) 0x4003A27: dl_main (rtld.c:1647) 223 | | ->01.34% (86,016B) 0x4019630: _dl_sysdep_start (dl-sysdep.c:249) 224 | | ->01.34% (86,016B) 0x4001C28: _dl_start (rtld.c:323) 225 | | ->01.34% (86,016B) 0x4000C36: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 226 | | 227 | ->00.89% (57,344B) in 1+ places, all below ms_print's threshold (01.00%) 228 | 229 ->03.12% (200,704B) 0xFFFFFFFFFFFFFFFF: ??? 230 | 231 ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) 232 233 -------------------------------------------------------------------------------- 234 n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) 235 -------------------------------------------------------------------------------- 236 21 89,190 6,340,608 6,340,608 0 0 237 100.00% (6,340,608B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc. 238 ->96.83% (6,139,904B) 0x401B4B9: mmap (mmap.c:34) 239 | ->95.87% (6,078,464B) 0x40068CB: _dl_map_object_from_fd (dl-map-segments.h:56) 240 | | ->95.87% (6,078,464B) 0x4008C25: _dl_map_object (dl-load.c:2498) 241 | | ->62.66% (3,973,120B) 0x400DBA0: openaux (dl-deps.c:63) 242 | | | ->62.66% (3,973,120B) 0x4010562: _dl_catch_error (dl-error.c:187) 243 | | | ->62.66% (3,973,120B) 0x400E1E0: _dl_map_object_deps (dl-deps.c:254) 244 | | | ->62.66% (3,973,120B) 0x4003A27: dl_main (rtld.c:1647) 245 | | | ->62.66% (3,973,120B) 0x4019630: _dl_sysdep_start (dl-sysdep.c:249) 246 | | | ->62.66% (3,973,120B) 0x4001C28: _dl_start (rtld.c:323) 247 | | | ->62.66% (3,973,120B) 0x4000C36: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 248 | | | 249 | | ->33.20% (2,105,344B) 0x4000EB3: map_doit (rtld.c:499) 250 | | ->33.20% (2,105,344B) 0x4010562: _dl_catch_error (dl-error.c:187) 251 | | ->33.20% (2,105,344B) 0x40020D4: handle_ld_preload (rtld.c:682) 252 | | ->33.20% (2,105,344B) 0x40039AD: dl_main (rtld.c:1539) 253 | | ->33.20% (2,105,344B) 0x4019630: _dl_sysdep_start (dl-sysdep.c:249) 254 | | ->33.20% (2,105,344B) 0x4001C28: _dl_start (rtld.c:323) 255 | | ->33.20% (2,105,344B) 0x4000C36: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 256 | | 257 | ->00.97% (61,440B) in 1+ places, all below ms_print's threshold (01.00%) 258 | 259 ->03.17% (200,704B) 0xFFFFFFFFFFFFFFFF: ??? 260 | 261 ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) 262 263 -------------------------------------------------------------------------------- 264 n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) 265 -------------------------------------------------------------------------------- 266 22 89,190 6,336,512 6,336,512 0 0 267 23 151,998 6,471,680 6,471,680 0 0
参考链接:
个性签名:时间会解决一切