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
參考鏈接: