debugallocator.hh: `operator new` not well-behaved; causes test failures with LTO
dune-common 2.8.0 fails to build in Debian with link-time optimization enabled due to failures in testdebugallocator.
A backtrace from gdb shows:
Program received signal SIGFPE, Arithmetic exception.
0x0000555555556cf1 in Dune::DebugMemory::AllocationManager::allocate<char> (this=<optimized out>, n=<optimized out>) at ./dune/common/debugallocator.hh:124
124 ai.page_ptr = mmap(NULL, ai.pages * page_size,
(gdb) bt
#0 0x0000555555556cf1 in Dune::DebugMemory::AllocationManager::allocate<char> (this=<optimized out>,
n=<optimized out>) at ./dune/common/debugallocator.hh:124
#1 operator new (size=size@entry=64) at ./dune/common/debugallocator.hh:322
#2 0x00007ffff7fb0e82 in __gnu_cxx::new_allocator<unsigned long>::allocate (this=<optimized out>,
__n=8) at /usr/include/c++/11/ext/new_allocator.h:127
#3 std::allocator_traits<std::allocator<bool*> >::allocate (__n=8, __a=<synthetic pointer>...)
at /usr/include/c++/11/bits/alloc_traits.h:464
#4 std::_Deque_base<bool, std::allocator<bool> >::_M_allocate_map (__n=8,
this=0x7ffff7fc36f8 <Dune::dvverb+24>) at /usr/include/c++/11/bits/stl_deque.h:576
#5 std::_Deque_base<bool, std::allocator<bool> >::_M_initialize_map (__num_elements=0,
this=0x7ffff7fc36f8 <Dune::dvverb+24>) at /usr/include/c++/11/bits/stl_deque.h:625
#6 std::_Deque_base<bool, std::allocator<bool> >::_Deque_base (this=0x7ffff7fc36f8 <Dune::dvverb+24>)
at /usr/include/c++/11/bits/stl_deque.h:439
#7 std::deque<bool, std::allocator<bool> >::deque (this=0x7ffff7fc36f8 <Dune::dvverb+24>)
at /usr/include/c++/11/bits/stl_deque.h:834
#8 std::stack<bool, std::deque<bool, std::allocator<bool> > >::stack<std::deque<bool, std::allocator<bool> >, void> (this=<optimized out>, this=<optimized out>) at /usr/include/c++/11/bits/stl_stack.h:163
#9 0x00007ffff7fb0f42 in _sub_I_65535_0.0 ()
from /build/dune-common-GdfBws/dune-common-2.8.0/build/lib/libdunecommon.so.2.8.0
#10 0x00007ffff7fdc0ce in ?? () from /lib64/ld-linux-x86-64.so.2
#11 0x00007ffff7fdc1b0 in ?? () from /lib64/ld-linux-x86-64.so.2
#12 0x00007ffff7fcd08a in ?? () from /lib64/ld-linux-x86-64.so.2
#13 0x0000000000000001 in ?? ()
#14 0x00007fffffffeccd in ?? ()
#15 0x0000000000000000 in ?? ()
This is during the construction of global objects, in particular some member of Dune::dvverb
.
It calls the custom operator new
from "debugallocator.hh".
The relevant instruction is:
=> 0x0000555555556cf1 <+81>: div %r12
which should come from this division:
ai.pages = (ai.capacity) / page_size + 2;
page_size
is still 0 as the global variables from the "debugallocator.cc" translation unit have not been initialized when the "Dune::dvverb" object gets constructed.
Note that the order in which global variables in different translation units are initialized is undefined according to the C++ standard, but the code currently requires a specific order (page_size
must be initialized before anything uses the operator new
).