2

I have overridden:

void* operator new(size_t count);

And when I construct an std::string it calls that function I'm assuming when it calls new. What I'm wondering is how does it know? The linker links with my function, not the standard C++ new. I understand the compiler can do this if it's linked statically with the runtime library (I'm guessing std::string) is defined(the code resides in) the runtime library. If it were linked statically with the runtime library then it would see the runtime library version, and my version, and since mine is "user-defined" it links with mine. However if the library is linked to a dll (runtime library), then a call to std::string's constructor resides in a .dll, which would call the standard operator new function. Is that what happens? Can a .dll call another library?

Anyway, I don't see how this is possible. My point being is that since the call to operator new isn't made in the header file of < string >, and since it's not linked statically, the compiler and linker doesn't even know that a call to operator new is made by the std::string constructor. On startup of the program the program looks for the String constructor and calls it in the .dll.

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • Does this answer your question? [How to properly replace global new & delete operators](https://stackoverflow.com/questions/8186018/how-to-properly-replace-global-new-delete-operators) – Jens Feb 21 '23 at 10:53
  • But if I do typedef unsigned int uint32 then I can use the function cast uint32(0), right? So strange. – Zebrafish Feb 21 '23 at 14:41

1 Answers1

0

For a start, it isn't an override. Overrides are when derived classes have functions with the same signature as a virtual function in the base class. Virtual function mechanics cannot work until after object creation, so that means operator new must either be global or class static.

The correct term is replaceable allocation functions.

Since they are replaceable, if you provide a replacement then your replacement will be used.

You give the example of std::string. Unfortunately this is somewhat complicated since, like many standard containers, std::string is templatized on an allocator, std::allocator<CharT> by default. So assuming that you don't use your own allocator then when std::string needs to allocate it will call std::allocator<T>::allocate()

Eventually this will call operator new.

Here I'm mainly referring to Unix like systems. I imagine that the situation is similar for Windows.

The linker can see everything. Your code that calls operator new (directly or indirectly). The C++ library that you are using. And any replacement allocators. If you are linking statically then it will need a static version of the C++ library. In that case all calls are resolved at link time.

In the case of shared libraries, the final link resolution is done by ld.so, the link loader. The link loader reads your executable and determines which libraries to load. This is transitive as shared libraries can also depend on other shared libraries. So the answer to "Can a .dll call another library?" is yes. You can use ldd -v to see the link loader dependencies of an executable (or a shared library).

Even if you don't replace allocation functions with libraries in your build system, it is still possible to do so at runtime. You can specify LD_PRELOAD to tell the link laoader to load additional libraries. So for instance if you want to use Google's tcmalloc you could use a script that does this

export LD_PRELOAD=/path/to/libtcmalloc.so
/path/to/my_application "$@"
Paul Floyd
  • 5,530
  • 5
  • 29
  • 43