https://docs.microsoft.com/en-us/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2019
对于比较明显的内存泄漏,vc2008是比较容易定位的,在Debug模式F5运行,退出时会列出引起内存泄漏的问题代码所在文件及行号;但如果是比较隐蔽的内存泄漏,Output输出窗口只会输出部分信息,形式如下:
Detected memory leaks!
Dumping objects ->
{858} normal block at 0x003ED290, 12 bytes long.
Data: < \H > A0 5C 48 00 00 00 00 00 00 00 00 00
Object dump complete.
我们来看一下输出信息的格式。
{xxx} — 表示程序运行后第xxx次内存分配发生了泄漏,即内存分配编号;
xxx block — 表示内存块类型,包括三种:普通(normal)、客户端(client)和运行时(CRT);
at 0xFFFFFFFF — 表示发生泄漏的内存地址,用十六进制表示;
xx bytes long — 表示发生泄漏的内存大小;
Data:xxx — 表示内存数据信息,一般输出前16字节的内容。
首先确定自己的程序使用的是哪个C运行库,方法是程序Propertise -> C/C++ -> Code Generation -> Runtime Library选项,若为Multi-threaded Debug(/MTd),则为静态链接,若为Multi-threaded Debug DLL(/MDd),则为动态链接。
然后按F11启动程序,程序会停在入口点。此时调出Watch窗口,
静态链接 在name项中输入_crtBreakAlloc,在value项中输入你要定位的内存分配编号;
动态链接 在name项中输入{,,msvcr90d.dll}_crtBreakAlloc,在value项中输入内存分配号。注意msvcr90d.dll是vc2008环境使用的运行库dll,若你用的是其他版本vc,请换成对应版本的dll。
现在按F5运行,程序就会自动定位到你要调试的内存分配语句,这时候看call stack的信息会很有帮助。
这个办法使用起来非常灵活,只要你确定内存分配号是不变的,就可以方便地为程序设置断点了,省去了更新代码和编译的麻烦。这个方法几乎是当前进行内存泄漏调试的最有效方法,如果你发现内存泄漏的分配号是变化的,可以想办法去掉一些没有问题的内存申请(多半是界面和多线程涉及到的申请),尽量使有问题的分配固定,就可以用这个方法排错了。
The memory allocation number tells you when a leaked memory block was allocated. A block with a memory allocation number of 18, for example, is the 18th block of memory allocated during the run of the app. The CRT report counts all memory-block allocations during the run, including allocations by the CRT library and other libraries such as MFC. Therefore, memory allocation block number 18 probably isn't the 18th memory block allocated by your code.
You can use the allocation number to set a breakpoint on the memory allocation.
To set a memory-allocation breakpoint using the Watch window:
Set a breakpoint near the start of your app, and start debugging.
When the app pauses at the breakpoint, open a Watch window by selecting Debug > Windows > Watch 1 (or Watch 2, Watch 3, or Watch 4).
In the Watch window, type _crtBreakAlloc
in the Name column.
If you're using the multithreaded DLL version of the CRT library (the /MD option), add the context operator: {,,ucrtbased.dll}_crtBreakAlloc
Press Enter.
The debugger evaluates the call and places the result in the Value column. This value will be -1 if you have not set any breakpoints on memory allocations.
In the Value column, replace the value with the allocation number of the memory allocation where you want the debugger to break.
After you set a breakpoint on a memory-allocation number, continue to debug. Make sure to run under the same conditions, so the memory-allocation number doesn't change. When your program breaks at the specified memory allocation, use the Call Stackwindow and other debugger windows to determine the conditions under which the memory was allocated. Then, you can continue execution to observe what happens to the object and determine why it isn't correctly deallocated.
Setting a data breakpoint on the object might also be helpful. For more information, see Using breakpoints.
You can also set memory-allocation breakpoints in code. You can set:
C++Copy
_crtBreakAlloc = 18;
or:
C++Copy
_CrtSetBreakAlloc(18);