This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: gcc 7.3: Replacing global operator new/delete in shared libraries


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?



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]