gcc 7.3: Replacing global operator new/delete in shared libraries
Martin Sebor
msebor@gmail.com
Wed Feb 7 23:38:00 GMT 2018
On 02/06/2018 03:56 PM, Paul Smith wrote:
> Hi all.
>
> Hopefully this isn't too annoying a question :).
>
> My environment has been using GCC 6.2 (locally compiled) on GNU/Linux
> systems. We use a separate heap management library (jemalloc) rather
> than the libc allocator. The way we did this in the past was to
> declare operator new/delete (all forms) as inline functions in a header
> and ensure that this header was always the very first thing in every
> source file, before even any standard header files. I know that inline
> operator new/delete isn't OK in the C++ standard, but in fact it has
> worked for us on the systems we care about.
I don't know if something has changed that would expose this
problem but...
I'm not sure I see how defining operator new inline can work
unless you recompile the world (i.e., all the DSOs used by
the program, including libstdc++). As Marc already hinted,
if libstdc++ dynamically allocates an object using the default
operator new and returns that object to the program to destroy,
it will end up causing a mismatch. The same can happen in
the opposite direction. To avoid such mismatches the entire
program needs to use a single operator new (each of
the required forms), and the only safe way to do that
is to define each out-of-line.
Martin
PS This question was the subject of C++ CWG issue 412:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#412
>
> I'm attempting a toolchain upgrade which is switching to GCC 7.3 /
> binutils 2.30 (along with many other updates).
>
> Now when I run our code, I get a core on exit. It appears an STL
> container delete is invoking libc free() with a pointer to memory
> allocated by jemalloc.
>
> I suspect that between 6.2 and 7.3 something in the STL has been
> modified to call new in a header file, so it's using our inline
> operator new, but call the matching delete from inside libstdc++.a (we
> link with static libstdc++ for portability), so it doesn't use our
> inline operator delete.
>
> While it's unfortunate for us, obviously that's a perfectly legal
> implementation choice. I don't know whether this is something the GCC
> folks care about. If so I can do more to track down the specifics.
>
> If I create a real global operator new/delete, even keeping the inlined
> versions, then the problem goes away (lending more weight to my guess
> above).
>
> I should point out that we don't use much STL memory so having some
> compiled (not header-based) STL use the libc allocator is not a big
> deal to us... it's just the mismatch which is a problem.
>
> This leads to my question:
>
> One of the things we provide is a shared library including much of our
> code, and also jemalloc. Users link this shared library with their
> code and we do not want them to use our allocator. By having all our
> operator new/delete inlined we are sure that all our requests go to our
> allocator and their requests do not. It's a bit grungy, perhaps, but
> it's worked well until now.
>
> My question is, what do I need to do to ensure this behavior persists
> if I create a global operator new/delete?
>
> Is it sufficient to ensure that the symbol for our shared library
> global new/delete symbols are hidden and not global, using a linker map
> or -fvisibility=hidden?
>
More information about the Gcc
mailing list