无替换值的#define _CRTDBG_MAP_ALLOC宏在预处理阶段如何处理?
无替换值宏的处理规则与_CRTDBG_MAP_ALLOC的作用原理
1 无替换值宏的预编译行为
这类仅定义宏名、没有配置替换内容的宏属于状态标识宏,预编译阶段不会对它做任何文本替换,它的唯一作用是标记「当前宏已被定义」的状态,供给后续的#ifdef/#if defined()等条件编译指令做判断。
举个简单的例子:你定义#define DEBUG后,所有被#ifdef DEBUG包裹的调试代码都会被保留参与编译,未定义该宏时这部分代码会被预编译阶段直接剔除,不会进入后续编译流程。
2 _CRTDBG_MAP_ALLOC的工作逻辑
你用到的_CRTDBG_MAP_ALLOC就是典型的状态标识宏,需要在引入crtdbg.h之前定义才会生效,原理如下:crtdbg.h内部存在对应这个宏的条件编译分支,当检测到该宏已被定义时,会自动完成两个替换:
- 将标准库的
malloc/free/new/delete等内存分配释放函数,替换为CRTDBG的调试版本_malloc_dbg/_free_dbg等,这类调试函数额外支持接收内存分配所在的文件名、行号参数,用于后续泄漏定位 - 头文件内置的宏封装会自动帮你补全文件名和行号参数,类似内置了定义
#define malloc(size) _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__),你直接调用原生malloc时预编译会自动填充参数,不需要你手动修改调用代码
3 你的测试代码的预编译等价结果
你给出的代码中malloc调用在预编译后会被自动替换为带定位信息的调试版调用,核心逻辑等价于:
#define _CRTDBG_MAP_ALLOC #include <iostream> #include <crtdbg.h> using namespace std; int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // 原生malloc自动替换为调试版,自动补全当前文件名、行号 int *ptr = (int*)_malloc_dbg(sizeof(int), _NORMAL_BLOCK, __FILE__, __LINE__); *ptr = 10; //free(ptr); return 0; }
程序退出时CRTDBG自动扫描未释放的内存块,就可以直接把记录的文件名、行号输出,帮你快速定位泄漏位置。
内容的提问来源于stack exchange,提问作者Meganathan
相关产品推荐
相关产品推荐

