C++ 宏定义如何用于内存泄漏检测?

C++ 宏定义如何用于内存泄漏检测?,c++,memory,macros,memory-leaks,C++,Memory,Macros,Memory Leaks,检测内存泄漏的简单方法是使用DEBUG_NEW宏,该宏定义如下 #ifdef _DEBUG #define new DEBUG_NEW #define DEBUG_NEW new(__FILE__, __LINE__) #endif 我发现了一个新的函数运算符,其定义如下: void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine); 如何在new(size\t nSize,LPCSTR lpszFileN

检测内存泄漏的简单方法是使用DEBUG_NEW宏,该宏定义如下

#ifdef _DEBUG
#define new DEBUG_NEW
#define DEBUG_NEW new(__FILE__, __LINE__)
#endif
我发现了一个新的函数运算符,其定义如下:

void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
如何在
new(size\t nSize,LPCSTR lpszFileName,int nLine
)中替换
new(\uuuuuu文件,\uuuuu行)


可以解释这个宏定义是如何工作的吗?

< P> C++禁止任何一个名字与词汇相同的宏的定义。由于
new
是一个关键字,因此禁止定义名为
new
的宏。您的编译器可能会拒绝具有此类宏定义的程序,或者您的程序可能会在编译或运行时表现出意外行为

这样,让我们考虑一个使用相同的宏诡计的良好的替代方案:

#define my_new DEBUG_NEW
#define DEBUG_NEW my_new(__FILE__, __LINE__)
这些宏依赖于宏替换是非递归的这一事实。让我们考虑一个例子,使用<代码> MyuNeX:

my_new T;
首先,
my_new
被标识为一个宏,并被其替换列表
DEBUG_new
替换。然后重新扫描替换列表以查找要替换的其他宏
DEBUG\u NEW
被标识为一个宏,并由其替换列表取代,
my\u NEW(\uuuu FILE\uuuu,\uuuu LINE\uuu)

此时,仍在评估原始
my\u new
的替换,因此替换列表中的
my\u new
的新实例不会再次被宏替换,因此保留为
my\u new
。这样可以确保在宏替换期间没有递归(或无限递归)的机会<代码>\\\\\\和
\\\\\\\\\\
被标识为宏,并被相应的值替换,从而产生以下最终结果:

my_new("clyde.cpp", 42) T;

《C++标准中<代码>新< /代码>的定义有三种:

throwing (1)  void* operator new (std::size_t size) throw (std::bad_alloc);
nothrow (2)   void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
placement (3) void* operator new (std::size_t size, void* ptr) throw();
第一个在失败时抛出
std::bad_alloc
异常,但第二个在失败时返回空指针。第三个是新的

对于
newint
,编译器将生成对
运算符new(sizeof(int))
的调用

nothrow\u值
参数仅用于将其与重载版本的第一个版本区分开来

MyClass * p2 = new (std::nothrow) MyClass;
它通过调用:
操作符new(sizeof(MyClass),std::nothrow)
来分配内存,然后在新分配的空间构造一个对象

因此,当我们编写以下代码时

MyClass * p2 = new(__FILE__, __LINE__) MyClass;
实际上,我们将
操作符称为new(sizeof(MyClass),\uuuuu FILE\uuuuu,\uuuuu LINE\uuuu)
。这就是我想知道的。 谢谢大家的帮助

其他定义包括:

__FILE__
此宏以C字符串常量的形式扩展为当前输入文件的名称。这是预处理器打开文件的路径,而不是#include或作为输入文件名参数指定的短名称。例如,“/usr/local/include/myheader.h”可能是此宏的扩展

__LINE__

此宏以十进制整数常量的形式扩展到当前输入行号。虽然我们称它为预定义宏,但它是一个非常奇怪的宏,因为它的“定义”随着每一行源代码的变化而变化。

Yeeek。如果有人试图使用placement new,或声明/定义类的分配例程,这将造成可怕的后果。不要重新定义关键字。放置新的关键字也是非常糟糕的做法。实际上没有人在新代码中使用位置。你能解释一下这个宏定义一般是如何工作的吗?我很想知道它是如何工作的?“实际上没有人在代码中使用新的位置。”错。我想知道这个宏定义是如何工作的?你能不能解释一下,不要说这不好?我知道,但我想知道更多。谢谢你的回答。你问:“有人能解释一下宏定义是如何工作的吗?”这就是宏定义的工作原理。如果这不是你想知道的,你想知道什么?更多关于什么?我在下面的回答中回答了我正在寻找的。请检查一下。你所解释的——每个程序员都应该知道这一点。谢谢