在存在 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,我可以更改。 HandleIdhed 命名空间属于该库。

我的问题:

  1. 有没有办法在 DEBUG_NEW 未注释的情况下编译它?
  2. 或者,有什么方法可以告诉 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 的情况下工作。