On Wed, 2018-02-07 at 11:32 +0100, Marc Glisse wrote: > On Tue, 6 Feb 2018, Paul Smith wrote: > > > 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 > > Are you sure you still have all forms? The aligned versions were > added in gcc-7 IIRC.
Hm. I didn't realize there were new forms in C++17; I had the throw and no-throw versions and also sized delete. No, I didn't create the new ones. I'll do that. > > 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. > > Inline usually works, but violating the ODR is harder... I would at > least use the always_inline attribute to improve chances (I assume > that static (or anonymous namespace) versions wouldn't work) I definitely do that already; for example: inline __attribute__((__always_inline__)) void* operator new(size_t size) ... > > 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. > > An example would help the discussion. Good point. Here's an example (from a unit test crash, in GTest): *** Error in `EncodedStreamTests.gtest': free(): invalid pointer: 0x00007ffff481d0a0 *** Program received signal SIGABRT, Aborted. 0x00007ffff4c62c37 in raise () from /lib/x86_64-linux-gnu/libc.so.6 (gdb) bt #0 0x00007ffff4c62c37 in raise () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff4c66028 in abort () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x00007ffff4c9f2a4 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #3 0x00007ffff4cab82e in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #4 0x0000000000539b89 in __gnu_cxx::new_allocator<char>::deallocate (this=<optimized out>, __p=<optimized out>) at /work/src/build/x86_64- linux/cc/generic/x86_64-generic-linux- gnu/include/c++/7.3.0/ext/new_allocator.h:125 #5 std::allocator_traits<std::allocator<char> >::deallocate (__a=..., __n=<optimized out>, __p=<optimized out>) at /work/src/build/x86_64- linux/cc/generic/x86_64-generic-linux- gnu/include/c++/7.3.0/bits/alloc_traits.h:462 #6 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_destroy (__size=<optimized out>, this=0x7fffffffe4e0) at /work/src/build/x86_64-linux/cc/generic/x86_64- generic-linux-gnu/include/c++/7.3.0/bits/basic_string.h:226 #7 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose (this=0x7fffffffe4e0) at /work/src/build/x86_64-linux/cc/generic/x86_64-generic-linux- gnu/include/c++/7.3.0/bits/basic_string.h:221 #8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string (this=0x7fffffffe4e0, __in_chrg=<optimized out>) at /work/src/build/x86_64- linux/cc/generic/x86_64-generic-linux- gnu/include/c++/7.3.0/bits/basic_string.h:647 #9 testing::internal::CodeLocation::~CodeLocation (this=0x7fffffffe4e0, __in_chrg=<optimized out>) at Tests/GTest/include/gtest/internal/gtest-internal.h:504 #10 testing::internal::MakeAndRegisterTestInfo (test_case_name=test_cas e_name@entry=0x5d8ed7 "ESTests", name=name@entry=0x5d8ec9 "bytesForCount", type_param=type_param@entry=0x0, value_param=value_par am@entry=0x0, code_location=..., fixture_class_id=fixture_class_id@entr y=0x65dd5c <testing::internal::TypeIdHelper<ESTests>::dummy_>, set_up_tc=0x48e010 <testing::Test::SetUpTestCase()>, tear_down_tc=0x48e020 <testing::Test::TearDownTestCase()>, factory=0x7ffff481c000) at Tests/GTest/src/gtest.cc:2580 #11 0x0000000000475286 in __static_initialization_and_destruction_0 (__priority=65535, __initialize_p=1) at EncodedStreamTests.cpp:351 #12 0x00000000005d8dcd in __libc_csu_init () #13 0x00007ffff4c4ded5 in __libc_start_main () from /lib/x86_64-linux- gnu/libc.so.6 #14 0x0000000000477375 in _start () > > 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? > > I think so (hidden implies not-interposable, so locally bound), but > I don't have much experience there. OK I'll pursue this for now. Thanks!