C检查内存泄露

windows下使用VS

方法一

在主函数最上端加上,否则无法显示行号

1
2
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>

然后,在主函数最后一句return 0;前面加上_CrtDumpMemoryLeaks();注意在debug下运行程序,就会出现在那一行多少字节的错误。

例如:

1
2
3
4
Detected memory leaks!
Dumping objects ->
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\network.c(37) : {150} normal block at 0x0000027FAD65DF60, 264 bytes long.
Data: < R > 00 00 52 15 0B 00 00 00 10 00 00 00 01 00 00 00

这时,在主函数开头加上一句_CrtSetBreakAlloc(150);,即可在内存泄露的语句停下,其实是与双击上面那句话找到的位置相同。

方法二

安装vld,然后在主函数所在的源程序加上

1
#include <vld.h>

即可查看泄露了多少内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
WARNING: Visual Leak Detector detected memory leaks!
-
Leak Hash: 0x1FFF84A9, Count: 1, Total 264 bytes
Call Stack (TID 11092):
ucrtbased.dll!calloc_dbg()
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\network.c (37): darknet_exe.exe!load_network_custom() + 0x2A bytes
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\network.c (49): darknet_exe.exe!load_network()
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\my_detect.c (70): darknet_exe.exe!my_load_weight() + 0x16 bytes
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\main.c (27): darknet_exe.exe!main() + 0x13 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (75): darknet_exe.exe!invoke_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (264): darknet_exe.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (309): darknet_exe.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): darknet_exe.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x14 bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
00 00 52 15 0B 00 00 00 10 00 00 00 01 00 00 00 ..R..... ........
D0 06 EA 83 47 02 00 00 00 00 00 00 01 00 00 00 ....G... ........
66 66 66 3F 6F 12 03 3A 80 C4 EB 83 47 02 00 00 fff?o..: ....G...
85 52 00 00 00 00 00 00 E0 8F 08 B9 47 02 00 00 .R...... ....G...
04 00 00 00 6F 12 83 3A 00 00 00 00 00 00 00 00 ....o..: ........
00 00 80 40 01 00 00 00 00 00 00 00 08 9D 00 00 ...@.... ........
B0 A1 E9 83 47 02 00 00 20 A0 E9 83 47 02 00 00 ....G... ....G...
04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
00 00 00 00 00 00 00 00 00 EC 07 00 A0 01 00 00 ........ ........
A0 01 00 00 03 00 00 00 40 03 00 00 A0 01 00 00 ........ @.......
01 00 00 00 00 00 00 00 00 00 80 3F 00 00 C0 3F ........ ...?...?
00 00 C0 3F CD CC CC 3D 00 00 00 00 00 00 00 00 ...?...= ........
00 00 00 00 00 00 00 00 00 00 54 19 0B 00 00 00 ........ ..T.....
B0 9C E9 83 47 02 00 00 00 9D E9 83 47 02 00 00 ....G... ....G...
50 9D E9 83 47 02 00 00 A0 9D E9 83 47 02 00 00 P...G... ....G...
E0 9E E9 83 47 02 00 00 30 9F E9 83 47 02 00 00 ....G... 0...G...

Visual Leak Detector detected 1 memory leak (316 bytes).
Largest number used: 275309586 bytes.
Total allocations: 318639983 bytes.
Visual Leak Detector is now exiting.

若你默认安装的话,该方法所读取的配置文件在C:\Program Files (x86)\Visual Leak Detector\vld.ini,可以修改该配置文件中的ReportTo = debuggerReportTo = both,即可同时保存信息到文本中与debugger总。

同时使用方法一和方法二

打印出来的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Detected memory leaks!
Dumping objects ->
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\network.c(37) : {150} normal block at 0x0000024783E909A0, 264 bytes long.
Data: < R > 00 00 52 15 0B 00 00 00 10 00 00 00 01 00 00 00
Object dump complete.
线程 0x29f4 已退出,返回值为 0 (0x0)。
线程 0x3970 已退出,返回值为 0 (0x0)。
线程 0xac4 已退出,返回值为 0 (0x0)。
线程 0x30fc 已退出,返回值为 0 (0x0)。
线程 0x3f50 已退出,返回值为 0 (0x0)。
线程 0x3ab4 已退出,返回值为 0 (0x0)。
线程 0x2a40 已退出,返回值为 0 (0x0)。
WARNING: Visual Leak Detector detected memory leaks!
-
Leak Hash: 0x1FFF84A9, Count: 1, Total 264 bytes
Call Stack (TID 11092):
ucrtbased.dll!calloc_dbg()
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\network.c (37): darknet_exe.exe!load_network_custom() + 0x2A bytes
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\network.c (49): darknet_exe.exe!load_network()
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\my_detect.c (70): darknet_exe.exe!my_load_weight() + 0x16 bytes
e:\darknet_yolo_windows_qt\darknet_vs_exportdll\src\runexe\main.c (27): darknet_exe.exe!main() + 0x13 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (75): darknet_exe.exe!invoke_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (264): darknet_exe.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (309): darknet_exe.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): darknet_exe.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x14 bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
00 00 52 15 0B 00 00 00 10 00 00 00 01 00 00 00 ..R..... ........
D0 06 EA 83 47 02 00 00 00 00 00 00 01 00 00 00 ....G... ........
66 66 66 3F 6F 12 03 3A 80 C4 EB 83 47 02 00 00 fff?o..: ....G...
85 52 00 00 00 00 00 00 E0 8F 08 B9 47 02 00 00 .R...... ....G...
04 00 00 00 6F 12 83 3A 00 00 00 00 00 00 00 00 ....o..: ........
00 00 80 40 01 00 00 00 00 00 00 00 08 9D 00 00 ...@.... ........
B0 A1 E9 83 47 02 00 00 20 A0 E9 83 47 02 00 00 ....G... ....G...
04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
00 00 00 00 00 00 00 00 00 EC 07 00 A0 01 00 00 ........ ........
A0 01 00 00 03 00 00 00 40 03 00 00 A0 01 00 00 ........ @.......
01 00 00 00 00 00 00 00 00 00 80 3F 00 00 C0 3F ........ ...?...?
00 00 C0 3F CD CC CC 3D 00 00 00 00 00 00 00 00 ...?...= ........
00 00 00 00 00 00 00 00 00 00 54 19 0B 00 00 00 ........ ..T.....
B0 9C E9 83 47 02 00 00 00 9D E9 83 47 02 00 00 ....G... ....G...
50 9D E9 83 47 02 00 00 A0 9D E9 83 47 02 00 00 P...G... ....G...
E0 9E E9 83 47 02 00 00 30 9F E9 83 47 02 00 00 ....G... 0...G...

Visual Leak Detector detected 1 memory leak (316 bytes).
Largest number used: 275309586 bytes.
Total allocations: 318639983 bytes.
Visual Leak Detector is now exiting.

Linux下

在要检查函数文件前面加上

1
#include <mcheck.h>

接着在main函数内部加上下面两句话,则最终信息会保留在mtrace.out文件中

1
2
setenv("MALLOC_TRACE", "mtrace.out", 1);
mtrace();

总的文件实例如下:

编译加上-g参数

------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道