在存在 DEBUG_NEW 宏的情况下重载 operator new
Overloaded operator new in the presence of DEBUG_NEW macro
在 MFC 项目中,我使用了外部库 TTL that overloads operator new
. My problem is that I have a memory leak and I'd like to make use of the diagnostics given by DEBUG_NEW
。但是我只能用 DEBUG_NEW
commented-out 编译它,否则我会得到下面的错误。
下面进行演示。当 Visual Studio 项目作为控制台应用程序 使用 MFC headers.
时,它是一个 MCVE
// The problem is when this is uncommented
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
struct HandleId
{
HandleId() {}
void* operator new (size_t t) {
return HandleId::operator new(t, 0, 0, 0);
};
void* operator new (size_t t, int, const char* file, int line) {
HandleId* tmp = (HandleId*)calloc(1, t);
return tmp;
};
void operator delete (void* v) {
free(v);
}
};
namespace hed
{
struct Node : public virtual HandleId
{
Node() {};
Node(double x, double y, double z = 0.0) {}
};
}
struct DtmNode : public hed::Node
{
DtmNode() {};
DtmNode(short pntRef, double x, double y, double z)
: hed::Node(x, y, z)
{};
};
int main()
{
DtmNode* pNode = new DtmNode(0, 1.0, 2.0, 3.0);
return 0;
}
在 DEBUG_NEW
未注释的情况下,上述编译失败 (VS2019) with.
error C2661: HandleId::operator new
: no overloaded function takes 3 arguments
到目前为止,我一直在使用宏commented-out。但我现在 do 希望在调试版本中使用它,原因很明显,可以帮助捕获调试期间的内存泄漏。 DtmNode
是我的 class,我可以更改。 HandleId
和 hed
命名空间属于该库。
我的问题:
- 有没有办法在
DEBUG_NEW
未注释的情况下编译它?
- 或者,有什么方法可以告诉
DtmNode
在 _DEBUG 模式下不要使用重载的 operator new
,以便按照 "normal" 使用 DEBUG_NEW
?
第一个问题的答案是 'no'。
您可以通过使用#pragma push_macro/pop_macro:
有选择地取消定义 new 来编译此类内容
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
...
int main()
{
#pragma push_macro("new")
#undef new
DtmNode* pNode = new DtmNode(0, 1.0, 2.0, 3.0);
#pragma pop_macro("new");
return 0;
}
它不允许您使用 MFC 的调试分配器跟踪库中的对象(为此您必须完全替换库的分配器)。但它至少可以让您的程序在存在不匹配的运算符 new 的情况下工作。
在 MFC 项目中,我使用了外部库 TTL that overloads operator new
. My problem is that I have a memory leak and I'd like to make use of the diagnostics given by DEBUG_NEW
。但是我只能用 DEBUG_NEW
commented-out 编译它,否则我会得到下面的错误。
下面进行演示。当 Visual Studio 项目作为控制台应用程序 使用 MFC headers.
时,它是一个 MCVE// The problem is when this is uncommented
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
struct HandleId
{
HandleId() {}
void* operator new (size_t t) {
return HandleId::operator new(t, 0, 0, 0);
};
void* operator new (size_t t, int, const char* file, int line) {
HandleId* tmp = (HandleId*)calloc(1, t);
return tmp;
};
void operator delete (void* v) {
free(v);
}
};
namespace hed
{
struct Node : public virtual HandleId
{
Node() {};
Node(double x, double y, double z = 0.0) {}
};
}
struct DtmNode : public hed::Node
{
DtmNode() {};
DtmNode(short pntRef, double x, double y, double z)
: hed::Node(x, y, z)
{};
};
int main()
{
DtmNode* pNode = new DtmNode(0, 1.0, 2.0, 3.0);
return 0;
}
在 DEBUG_NEW
未注释的情况下,上述编译失败 (VS2019) with.
error C2661:
HandleId::operator new
: no overloaded function takes 3 arguments
到目前为止,我一直在使用宏commented-out。但我现在 do 希望在调试版本中使用它,原因很明显,可以帮助捕获调试期间的内存泄漏。 DtmNode
是我的 class,我可以更改。 HandleId
和 hed
命名空间属于该库。
我的问题:
- 有没有办法在
DEBUG_NEW
未注释的情况下编译它? - 或者,有什么方法可以告诉
DtmNode
在 _DEBUG 模式下不要使用重载的operator new
,以便按照 "normal" 使用DEBUG_NEW
?
第一个问题的答案是 'no'。
您可以通过使用#pragma push_macro/pop_macro:
有选择地取消定义 new 来编译此类内容#ifdef _DEBUG
#define new DEBUG_NEW
#endif
...
int main()
{
#pragma push_macro("new")
#undef new
DtmNode* pNode = new DtmNode(0, 1.0, 2.0, 3.0);
#pragma pop_macro("new");
return 0;
}
它不允许您使用 MFC 的调试分配器跟踪库中的对象(为此您必须完全替换库的分配器)。但它至少可以让您的程序在存在不匹配的运算符 new 的情况下工作。