问题
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.
回答1:
Here's how we do it (with jemalloc, but any other allocator is possible):
- Compile the custom memory allocator separately as a C static library.
- Link your C++ application with the custom allocator library.
- Override operators
new
anddelete
in your C++ application to invoke the custom allocator.
Notes:
- The custom allocator must to be written in C, not C++.
- It is not possible to ensure sufficiently early initialization of the allocator unless it resides in a separate library.
- Overriding
malloc
andfree
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);
}
来源:https://stackoverflow.com/questions/12815867/overriding-memory-allocator-in-msvc