勘误和补充

Windows用户态程序高效排错 勘误
===
文章中的疏漏,错误的修正会放在这里。

===

第11页,错误的句子:

 

问题一共就发生过三次,是通过分析log文件得到的。Log文件记录的是每个时刻Session中的内。

应该修改为:

问题一共就发生过三次,是通过分析log文件得到的。Log文件记录的是每个log生成时刻Session中的内容。

==

 

如果在VS2005下面想用CRT Debug Heap来调试Memory Leak,最后可以用_CrtDumpMemoryLeaks 把所有的leak打印出来。尝试下面的代码,会怎样:

#include "stdafx.h"

#ifdef _DEBUG

#define _CRTDBG_MAP_ALLOC

#include<stdlib.h>

#include<crtdbg.h>

#endif

#define MY_NEW[s] new(s,_NORMAL_BLOCK, __FILE__, __LINE__)

#if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC)

#define new MY_NEW

#endif

int _tmain(int argc, _TCHAR* argv[])

{

   

    char *p=new char[10];

    void *p2=malloc(10);

    #ifdef _DEBUG

    _CrtDumpMemoryLeaks();

#endif

    return 0;

}

运行后会看到:

Detected memory leaks!

Dumping objects ->

c:\documents and settings\lixiong\my documents\mycode\detectleak\detectleak\detectleak.cpp(17) : {87} normal block at 0x003A8130, 10 bytes long.

 Data: < > CD CD CD CD CD CD CD CD CD CD

c:\program files\microsoft visual studio 8\vc\include\crtdbg.h(1150) : {86} normal block at 0x003A3240, 10 bytes long.

 Data: < > CD CD CD CD CD CD CD CD CD CD

Object dump complete.

The program '[808] DetectLeak.exe: Native' has exited with code 0 (0x0).

注意这里打印出的第一个leak,出现在detectleak.cpp的17行,对应的是malloc语句,没问题

可是第二个leak,出现在crtdbg.h的1150行,而不是new char[10]那里,怎么回事?如果不能定位到正确的源代码,还有什么用呢?

为了搞清楚这个问题,可以看看malloc在debug heap下的的定义:

#ifdef  _CRTDBG_MAP_ALLOC

#define   malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

注意看,这里用了__FILE__, __LINE__两个预处理器Directive:

The #line Directive
https://msdn2.microsoft.com/en-us/library/b5w2czay.aspx

由于与处理器自动把文件名和行号传递给了_malloc_dbg函数,最后的output窗口才可以打印出源代码行

那好,看看debug heap的new的定义。由于new是C++的关键字,而且是一个操作符,所以debug heap下定义为:

inline __bcount(_Size) void* __CRTDECL operator new[](size_t _Size)

        { return ::operator new[](_Size, _NORMAL_BLOCK, __FILE__, __LINE__); }

注意这里没有用#define,而是inline。同时该定义是在crtdbg.h文件中的。所以最后得到的是文件名是crtdbg.h。你可能有如下疑问:

1. 为什么不用#define而要用inline呢,改成#define可以吗?
你试试看吧,看能不能该成#define。由于这里有一个中括号,麻烦来了吧。谁让你是C++呢?bs一下C++

2. 为什么预处理器看到inline函数,不把inline后的行号和文件名字作为解释呢?
这我就不确定了啦。不过根据C++标准,标示为inline函数不是一定就要inline的,人家标准就定义得模棱两可,你何必强求预处理器呢?

所以,解决方法就是,所有的内存分配,就用:

#ifdef _CRTDBG_MAP_ALLOC

    char *test=(char*)::operator new[](20, _NORMAL_BLOCK, __FILE__, __LINE__);

#else

    char *test=new char[20];

#endif

你有其它好方法吗?