为什么是新&;是否要重新定位共享obj中的删除运算符符号,即使它们在该共享obj中实现? 我尝试在程序中实现我自己的C++新的和删除操作符,如: #include <stdio.h> #include <stdlib.h> #include <new> using namespace std; void *operator new(std::size_t size) throw(std::bad_alloc) { printf("My new is called!\n"); return malloc(size); } void operator delete(void *ptr) throw () { printf("My delete is called!\n"); free(ptr); } void *operator new(std::size_t size, const std::nothrow_t&) throw() { return malloc(size); } void operator delete(void *ptr, const std::nothrow_t&) throw() { free(ptr); } void *operator new[](std::size_t size) throw(std::bad_alloc) { return malloc(size); } void operator delete[](void *ptr) throw () { free(ptr); } void *operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc(size); } void operator delete[](void *ptr, const std::nothrow_t&) throw() { free(ptr); } class Object { public: Object() {} ~Object() {} private: int a; }; int main() { Object* obj = new Object(); if (obj) delete obj; return 0; } #包括 #包括 #包括 使用名称空间std; void*运算符新建(std::size\u t size)抛出(std::bad\u alloc) { printf(“我的新名字叫!\n”); 返回malloc(大小); } void操作符删除(void*ptr)抛出() { printf(“我的删除被称为!\n”); 免费(ptr); } void*运算符new(std::size\u t size,const std::nothrow\u t&)throw() { 返回malloc(大小); } void操作符delete(void*ptr,const std::nothrow\u t&)throw() { 免费(ptr); } void*运算符新[](标准::大小\u t大小)抛出(标准::错误\u分配) { 返回malloc(大小); } void操作符delete[](void*ptr)throw() { 免费(ptr); } void*运算符新[](标准::大小\u t大小, 常量std::nothrow\u t&)throw() { 返回malloc(大小); } void运算符delete[](void*ptr, 常量std::nothrow\u t&)throw() { 免费(ptr); } 类对象 { 公众: 对象(){} ~Object(){} 私人: INTA; }; int main() { Object*obj=新对象(); 如果(obj) 删除obj; 返回0; }

为什么是新&;是否要重新定位共享obj中的删除运算符符号,即使它们在该共享obj中实现? 我尝试在程序中实现我自己的C++新的和删除操作符,如: #include <stdio.h> #include <stdlib.h> #include <new> using namespace std; void *operator new(std::size_t size) throw(std::bad_alloc) { printf("My new is called!\n"); return malloc(size); } void operator delete(void *ptr) throw () { printf("My delete is called!\n"); free(ptr); } void *operator new(std::size_t size, const std::nothrow_t&) throw() { return malloc(size); } void operator delete(void *ptr, const std::nothrow_t&) throw() { free(ptr); } void *operator new[](std::size_t size) throw(std::bad_alloc) { return malloc(size); } void operator delete[](void *ptr) throw () { free(ptr); } void *operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc(size); } void operator delete[](void *ptr, const std::nothrow_t&) throw() { free(ptr); } class Object { public: Object() {} ~Object() {} private: int a; }; int main() { Object* obj = new Object(); if (obj) delete obj; return 0; } #包括 #包括 #包括 使用名称空间std; void*运算符新建(std::size\u t size)抛出(std::bad\u alloc) { printf(“我的新名字叫!\n”); 返回malloc(大小); } void操作符删除(void*ptr)抛出() { printf(“我的删除被称为!\n”); 免费(ptr); } void*运算符new(std::size\u t size,const std::nothrow\u t&)throw() { 返回malloc(大小); } void操作符delete(void*ptr,const std::nothrow\u t&)throw() { 免费(ptr); } void*运算符新[](标准::大小\u t大小)抛出(标准::错误\u分配) { 返回malloc(大小); } void操作符delete[](void*ptr)throw() { 免费(ptr); } void*运算符新[](标准::大小\u t大小, 常量std::nothrow\u t&)throw() { 返回malloc(大小); } void运算符delete[](void*ptr, 常量std::nothrow\u t&)throw() { 免费(ptr); } 类对象 { 公众: 对象(){} ~Object(){} 私人: INTA; }; int main() { Object*obj=新对象(); 如果(obj) 删除obj; 返回0; },c++,linker,relocation,C++,Linker,Relocation,然后我发现,如果该程序构建为: --一个exe,然后按预期调用my new/delete --但是,一个共享对象,则new&delete的符号将被重新定位,因此在my env中,当dlopen在另一个程序中加载此so时,new&delete将映射到另一个程序的new&delete 详细信息如下所示 生成一个exe: gcc-m32-c main.cpp gcc-m32 main.o-o main.exe $./main.exe 我的新名字叫! 我的删除被调用 $objdump-d main.ex

然后我发现,如果该程序构建为: --一个exe,然后按预期调用my new/delete --但是,一个共享对象,则new&delete的符号将被重新定位,因此在my env中,当dlopen在另一个程序中加载此so时,new&delete将映射到另一个程序的new&delete

详细信息如下所示

  • 生成一个exe:

    gcc-m32-c main.cpp gcc-m32 main.o-o main.exe

    $./main.exe 我的新名字叫! 我的删除被调用

    $objdump-d main.exe 080484ac:
    80484ac:55推力%ebp
    80484ad:89 e5 mov%esp,%ebp
    80484af:53推送%ebx
    80484b0:83 ec 24子$0x24,%esp
    80484b3:83 e4 f0和$0xfffffff0,%esp
    80484b6:b8 00 mov$0x0,%eax
    80484bb:83 c0 0f添加$0xf,%eax
    80484be:83 c0 0f添加$0xf,%eax
    80484c1:c1 e8 04 shr$0x4,%eax
    80484c4:c1 e0 04 shl$0x4,%eax
    80484c7:29 c4子%eax,%esp
    80484c9:c7 04 24 04 00 movl$0x4,(%esp)
    80484d0:e8 1f ff ff呼叫80483f4-->新:预计
    80484d5:89 c3 mov%eax,%ebx
    80484d7:89 1c 24 mov%ebx,(%esp)
    80484da:e8 35 00 00呼叫8048514
    80484df:89 5d f8 mov%ebx,-0x8(%ebp)
    80484e2:83 7d f8 00 cmpl$0x0,-0x8(%ebp)
    80484e6:74 22 je 804850a
    80484e8:8b 45 f8 mov-0x8(%ebp),%eax
    80484eb:89 45 e8 mov%eax,-0x18(%ebp)
    80484ee:83 7d e8 00 cmpl$0x0,-0x18(%ebp)
    80484f2:74 16 je 804850a
    80484f4:8b 45 e8 mov-0x18(%ebp),%eax
    80484f7:89 04 24 mov%eax,(%esp)
    80484fa:e8 1b 00呼叫804851a
    80484ff:8b 45 e8 mov-0x18(%ebp),%eax
    8048502:89 04 24 mov%eax,(%esp)
    8048505:e8 0a ff呼叫8048414-->删除:预期

  • 构建共享对象:

    gcc-m32-c main.cpp gcc—共享的-m32 main.o-o main.so

    $objdump-d main.so 000006d4:
    6d4:55%推压ebp
    6d5:89 e5 mov%esp,%ebp
    6d7:53推送百分比ebx
    6d8:83 ec 24子$0x24,%esp
    6db:83 e4 f0和$0xfffffff0,%esp
    6de:B800 mov$0x0,%eax
    6e3:83 c0 0f添加$0xf,%eax
    6e6:83 c0 0f添加$0xf,%eax
    6e9:c1 e8 04 shr$0x4,%eax
    6ec:c1 e0 04 shl$0x4,%eax
    6ef:29 c4次%eax,%esp
    6f1:c7 04 24 04 00 movl$0x4,(%esp)
    6f8:e8 fc ff呼叫6f9-->新:要重新定位,意外:(
    6fd:89 c3 mov%eax,%ebx
    6ff:89 1c 24 mov%ebx,(%esp)
    702:e8 fc ff呼叫703
    707:89 5d f8 mov%ebx,-0x8(%ebp)
    70a:83 7d f8 00 cmpl$0x0,-0x8(%ebp)
    70e:74 22 je 732
    710:8b 45 f8 mov-0x8(%ebp),%eax
    713:89 45 e8 mov%eax,-0x18(%ebp)
    716:83 7d e8 00 cmpl$0x0,-0x18(%ebp)
    71a:7416JE732
    71c:8b 45 e8 mov-0x18(%ebp),%eax
    71f:89 04 24 mov%eax,(%esp)
    722:e8 fc ff呼叫723-->删除:要重新定位,意外:(
    727:8b 45 e8 mov-0x18(%ebp),%eax
    72a:89 04 24 mov%eax,(%esp)
    72d:e8 fc ff呼叫72e

  • 但是,如果是共享对象,则需要重新定位new&delete的符号

    这与设计完全一样(UNIX共享库在这方面的工作方式与Windows共享库非常不同)

    原因:符号插入。例如,在UNIX上,您可以将替代的malloc实现(例如tcmalloc)链接到主可执行文件中,每个共享库,包括
    libc。因此提供自己的malloc的
    将调用您的malloc

    如果你想