Reputation: 76296
While Microsoft standard runtime provides debugging version of allocation functions, it does not really work, because you are not supposed to use naked new in C++ code, so the instrumentation points to standard library, or nowhere because standard library can't be instrumented anyway.
Now I have code that can produce (and record) backtraces of allocations and I also used DUMA. However attempts at replacing the allocation functions broke when we used streams, because streambuf
calls to some debug variant and does so inconsistently between new and delete.
So does anybody have experience with replacing allocator, by overriding the functions, not ugly preprocessor tricks, in Microsoft standard runtime? I suspect it involves avoiding the debug allocator, but I want to keep the _DEBUG
define for obvious reasons (a lot more debug code depends on it).
Note: we are currently stuck with Visual C++ 9.0 (Visual Studio 2008).
Edit: Avoiding the debug allocator is unlikely to be an option, because the C++ standard library needs to have consistent definitions of new and delete between the functions and instantiations compiled to the library and the instantiations generated in user code since allocation might be done by one and release by the other. That by the way means that defining static inline variants in force-included header is unlikely to cut it.
Edit2: It's not possible with dynamic linking, because Windows bind symbols from specific DLLs, so there is no way to override them at link-time. But we don't need dynamic linking and don't use it because the primary target is WinCE and static linking is default there.
Upvotes: 4
Views: 2733
Reputation: 85371
Here's how we do it (with jemalloc, but any other allocator is possible):
new
and delete
in your C++ application to invoke the custom allocator.Notes:
malloc
and free
is also possible but a lot harder in MSVC, because those are not "weakly"-linked, and because there are a lot of custom variants in MSVC (for example using the /FORCE:MULTIPLE
linker flag).Sample code:
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);
}
Upvotes: 2