Why new&delete operator symbols in shared-obj is to be relocated even if they are implemented in that shared-obj?

StackOverflow https://stackoverflow.com/questions/10765888

  •  11-06-2021
  •  | 
  •  

Question

I am try to implement my own c++ new & delete operators in my program as bellow:

#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;
}

Then I find that, if the program is built out as: -- an exe, then my new/delete is called as expected -- but,, a shared-object, then symbols of new & delete is to be relocated, so in my env when this so is loaded by dlopen in another program then the new & delete will be mapped to another program's new & delete...

The detailed information is as bellow...

  1. build out an exe:

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

    $ ./main.exe My new is called! My delete is called!

    $ objdump -d main.exe 080484ac :
    80484ac: 55 push %ebp
    80484ad: 89 e5 mov %esp,%ebp
    80484af: 53 push %ebx
    80484b0: 83 ec 24 sub $0x24,%esp
    80484b3: 83 e4 f0 and $0xfffffff0,%esp
    80484b6: b8 00 00 00 00 mov $0x0,%eax
    80484bb: 83 c0 0f add $0xf,%eax
    80484be: 83 c0 0f add $0xf,%eax
    80484c1: c1 e8 04 shr $0x4,%eax
    80484c4: c1 e0 04 shl $0x4,%eax
    80484c7: 29 c4 sub %eax,%esp
    80484c9: c7 04 24 04 00 00 00 movl $0x4,(%esp)
    80484d0: e8 1f ff ff ff call 80483f4 <_Znwj> --> new: expected!!
    80484d5: 89 c3 mov %eax,%ebx
    80484d7: 89 1c 24 mov %ebx,(%esp)
    80484da: e8 35 00 00 00 call 8048514 <_ZN6ObjectC1Ev>
    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 00 00 call 804851a <_ZN6ObjectD1Ev>
    80484ff: 8b 45 e8 mov -0x18(%ebp),%eax
    8048502: 89 04 24 mov %eax,(%esp)
    8048505: e8 0a ff ff ff call 8048414 <_ZdlPv> --> delete: expected

  2. build out a shared object:

    gcc -m32 -c main.cpp gcc --shared -m32 main.o -o main.so

    $ objdump -d main.so 000006d4 :
    6d4: 55 push %ebp
    6d5: 89 e5 mov %esp,%ebp
    6d7: 53 push %ebx
    6d8: 83 ec 24 sub $0x24,%esp
    6db: 83 e4 f0 and $0xfffffff0,%esp
    6de: b8 00 00 00 00 mov $0x0,%eax
    6e3: 83 c0 0f add $0xf,%eax
    6e6: 83 c0 0f add $0xf,%eax
    6e9: c1 e8 04 shr $0x4,%eax
    6ec: c1 e0 04 shl $0x4,%eax
    6ef: 29 c4 sub %eax,%esp
    6f1: c7 04 24 04 00 00 00 movl $0x4,(%esp)
    6f8: e8 fc ff ff ff call 6f9 ---> new: to be relocated, unexpected :(
    6fd: 89 c3 mov %eax,%ebx
    6ff: 89 1c 24 mov %ebx,(%esp)
    702: e8 fc ff ff ff call 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: 74 16 je 732
    71c: 8b 45 e8 mov -0x18(%ebp),%eax
    71f: 89 04 24 mov %eax,(%esp)
    722: e8 fc ff ff ff call 723 ---> delete: to be relocated, unexpected :(
    727: 8b 45 e8 mov -0x18(%ebp),%eax
    72a: 89 04 24 mov %eax,(%esp)
    72d: e8 fc ff ff ff call 72e

Was it helpful?

Solution

but, a shared-object, then symbols of new & delete is to be relocated

This is exactly as designed (UNIX shared libraries work very differently from Windows shared libraries in that respect).

The reason: symbol interpositioning. For example, on UNIX you can link in an alternative malloc implementation (e.g. tcmalloc) into the main executable, and every shared library, including libc.so which provides its own malloc, will call your malloc.

If you want to achieve Windows-like symbol binding on UNIX, the -Bsymbolic linker flag might do what you want (read man ld on your platform).

If you are on Linux or Solaris, gcc -shared -Wl,-Bsymbolic ... should do what you want. Beware: there are many gotcha's in going "against the system". You may come to regret trying to do it this way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top