new
和delete
内存跟踪重载的内容
我定义了这些全局运算符:
inline void* __cdecl operator new( unsigned int size, const char *file, int line ) {
void* ptr = malloc( size );
AddTrack((DWORD)ptr, size, file, line);
return ptr;
}
inline void* __cdecl operator new( unsigned int size, void* ptr, const char *file, int line ) {
return ptr;
}
它适用于新的和新的[]运算符,但我有一个新的放置(第二个)的问题。我的定义看起来像:
#define new new( __FILE__, __LINE__)
#define new(x) new( x, __FILE__, __LINE__)
他们分开工作。但是当我尝试使用它们时,都会出现错误。据我所知,他们互相替代。我知道我可以使用像这样可变数量的参数的宏:
#define new( ... ) new( __VA_ARGS__, __FILE__, __LINE__)
但是我需要有和没有参数的相同的宏,所以这些行中的new
- s替换为右:
g_brushes = new Brush[ num_brushes ];
...
new( &g_brushes[i] )Brush(sides);
答案 0 :(得分:4)
如果你决定走上覆盖全球新道路的黑暗道路,你必须确保考虑以下所有场景:
new Foo; // 1
new Foo[10]; // 2
new (std::nothrow) Foo; // 3
new (p) Foo; // 4 - placement, not overridable
(Foo*) ::operator new(sizeof(Foo)); // 5 - direct invocation of the operator
应该可以处理除上一个之外的所有上述内容。颤动。
必要的knol和手法是你的宏应以new
结尾。当您的宏以new
结尾时,您可以将调用它的不同方式委托给new
本身。
这是一种非线程安全的方法。定义一个类型来捕获调用的上下文,这样我们以后就可以在运算符本身中检索这个上下文,
struct new_context {
new_context(const char* file, const int line)
: file_(file), line_(line) { scope_ = this; }
~new_context() { scope_ = 0; }
static new_context const& scope() { assert(scope_); return *scope_; }
operator bool() const { return false; }
const char* file_;
const int line_;
private:
static new_context* scope_;
};
接下来,定义覆盖以在调用之前创建new_context
临时
#define new new_context(__FILE__, __LINE__) ? 0 : new
使用三元运算符条件赋值在委托给operator new之前计算表达式,注意它是我们在上面定义的operator bool
得到的便利。
然后在你的新覆盖内(我将在这里使用标准C ++ 98而不是MSC C ++),你所要做的就是检索上下文:
void* operator new (std::size_t size) throw (std::bad_alloc) {
std::cout
<< "new"
<< "," << new_context::scope().file_
<< ":" << new_context::scope().line_
<< std::endl;
return 0;
}
这种方法将处理上面的所有案例1-4
,重要且容易被忽视的是4
未调用重载的情况,因为无法替换放置新的(§18.4.1.3),您仍然知道新的展示位置是因为new_context
将被创建和销毁。
总而言之,您无需修改new
运算符后面的内容,因此所有可能的语法仍然有效。另一点是new_context
对象临时将保持活动直到操作员参与的表达式结束,因此您可以安全地从全局单例中获取它。
<强> See a gcc example live 即可。 适应MSC留给读者。