假设我要向分配的对象添加一些元信息,以跟踪分配/取消分配。 我了解到足以替换一个operator new版本和两个operator delete版本来处理自C ++ 11以来的所有分配。
这是我写的:
#include <cstdlib>
#include <FreeImage.h>
#include <new>
#include <iostream>
void *operator new(size_t size)
{
std::cout << "allocation of size " << size << '\n';
void *allocated = malloc(size + sizeof(size_t));
*reinterpret_cast<size_t *>(allocated) = size;
return reinterpret_cast<void *>(reinterpret_cast<size_t *>(allocated) + 1);
}
void _delete(void *ptr) {
void *allocated = reinterpret_cast<void *>(reinterpret_cast<size_t *>(ptr) - 1);
size_t size = *reinterpret_cast<size_t *>(allocated);
std::cout << "deallocation of size " << size << '\n';
free(allocated);
}
void operator delete(void *ptr) noexcept
{
_delete(ptr);
}
void operator delete(void *ptr, std::align_val_t al) noexcept
{
_delete(ptr);
}
int main()
{
auto str = new char[1337];
delete str;
FreeImage_Initialise();
}
// compiled with `g++ -std=c++17 reproduce.cpp -lfreeimage`
如果我不使用任何第三方功能,则此程序有效,但如果使用第三方功能,则此程序将失败。
使用free(): invalid pointer
和gdb导致程序崩溃,它在_delete内部失败,我想这意味着某些内容是使用标准分配器分配的,但已由我自己的释放。
GDB输出:
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff79a9535 in __GI_abort () at abort.c:79
#2 0x00007ffff7a10516 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7b34c00 "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3 0x00007ffff7a173aa in malloc_printerr (str=str@entry=0x7ffff7b32d85 "free(): invalid pointer") at malloc.c:5336
#4 0x00007ffff7a191fc in _int_free (av=<optimized out>, p=<optimized out>, have_lock=<optimized out>) at malloc.c:4143
#5 0x00005555555552e8 in _delete(void*) ()
#6 0x0000555555555303 in operator delete(void*) ()
#7 0x00007ffff7d7edc2 in ?? () from /usr/lib/x86_64-linux-gnu/libfreeimage.so.3
#8 0x00007ffff79cba77 in __cxa_finalize (d=0x7ffff7fa0000) at cxa_finalize.c:83
#9 0x00007ffff7d17003 in ?? () from /usr/lib/x86_64-linux-gnu/libfreeimage.so.3
#10 0x00007fffffffdec0 in ?? ()
#11 0x00007ffff7fe3d16 in _dl_fini () at dl-fini.c:138
问题是:如何正确更换新的/删除的?
答案 0 :(得分:2)
我找到了我的案子的答案。
我替换了这些表格以使其起作用:
void *operator new(size_t size);
void *operator new(size_t size, std::align_val_t al);
void *operator new(size_t size, const std::nothrow_t &tag);
void *operator new(std::size_t size, std::align_val_t al, const std::nothrow_t &);
void operator delete(void *ptr);
尽管我没有替换对齐的删除运算符,但程序停止崩溃。 但是我想替换cppreference.com建议的替换对齐的删除仍然是一个好主意。