虽然Microsoft标准运行时提供分配函数的调试版本,但实际上并不起作用,因为您不应该在C ++代码中使用裸新,因此检测指向标准库,或者因为标准库不能无论如何都是仪表化的。
现在我有了可以生成(并记录)分配回溯的代码,我也使用了DUMA。但是,当我们使用流时,替换分配函数的尝试就会中断,因为streambuf
调用了某些调试变体,并且在new和delete之间不一致。
在Microsoft标准运行时中,是否有人通过覆盖函数而不是丑陋的预处理器技巧来替换allocator?我怀疑它涉及避免调试分配器,但我想保留_DEBUG
定义的原因显而易见(更多的调试代码取决于它)。
注意:我们目前仍处于使用Visual C ++ 9.0(Visual Studio 2008)。
编辑:避免调试分配器不太可能是一个选项,因为C ++标准库需要在编译到库的函数和实例化与用户代码中生成的实例化之间具有一致的new和delete定义,因为分配可能是一个完成,另一个释放。顺便说一下,在强制包含标题中定义静态内联变体不太可能削减它。
Edit2:动态链接是不可能的,因为Windows绑定来自特定DLL的符号,因此无法在链接时覆盖它们。但是我们不需要动态链接而不使用它,因为主要目标是WinCE,静态链接是默认链接。
答案 0 :(得分:1)
这是我们如何做到的(使用jemalloc,但任何其他分配器都是可能的):
new
和delete
以调用自定义分配器。注意:
malloc
和free
也是可能的,但在MSVC中要难得多,因为它们并非“弱”链接,并且因为MSVC中有很多自定义变体(例如使用/FORCE:MULTIPLE
链接器标志)。示例代码:
void* operator new(size_t size)
{
void* ptr = my_malloc(size);
if (ptr)
return ptr;
else
throw std::bad_alloc();
}
void* operator new[](size_t size)
{
void* ptr = my_malloc(size);
if (ptr)
return ptr;
else
throw std::bad_alloc();
}
void* operator new(size_t size, const std::nothrow_t&) throw()
{
return my_malloc(size);
}
void* operator new[](size_t size, const std::nothrow_t&) throw()
{
return my_malloc(size);
}
void operator delete(void* pointer) throw()
{
my_free(pointer);
}
void operator delete[](void* pointer) throw()
{
my_free(pointer);
}
void operator delete(void* pointer, const std::nothrow_t&) throw()
{
my_free(pointer);
}
void operator delete[](void* pointer, const std::nothrow_t&) throw()
{
my_free(pointer);
}