1

I'm having a hard time debugging this issue: https://github.com/cnjinhao/nana/issues/445

I have previously asked about LTO vs static object initialization and edited the library's code to implement Meyer's singletons so that the correct order of initialization happens. Hello worlds still crash, although library's functions have mostly dissappeared from stack traces:

#include <nana/paint/graphics.hpp>
int main()
{
    nana::paint::font f;
}
Thread 1 received signal SIGSEGV, Segmentation fault.
(gdb) bt
#0  0x00000000004985cf in std::type_info::operator==(std::type_info const&) const ()
#1  0x0000000000455180 in __cxxabiv1::__vmi_class_type_info::__do_dyncast(long long, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result&) const ()
#2  0x00000000004eae07 in __dynamic_cast ()
#3  0x00000000004e6625 in bool std::has_facet<std::ctype<char> >(std::locale const&) ()
#4  0x00000000004e1f74 in std::basic_ios<char, std::char_traits<char> >::_M_cache_locale(std::locale const&) ()
#5  0x00000000004e20c0 in std::basic_ios<char, std::char_traits<char> >::init(std::basic_streambuf<char, std::char_traits<char> >*) ()
#6  0x00000000004dfe2b in std::ios_base::Init::Init() ()
#7  0x0000000000431f2f in __static_initialization_and_destruction_0(int, int) [clone .lto_priv.4] ()
#8  0x0000000000431f59 in _GLOBAL__sub_I__ZN4nana6detail18drawable_impl_typeC2Ev ()
#9  0x00000000004398c9 in global constructors keyed to 65535_0_objects.a_0x8e.19316 ()
#10 0x00000000004432b3 in __do_global_ctors ()
    at E:/GitHub/MINGW-packages/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:67
#11 0x00000000004432fb in __main ()
    at E:/GitHub/MINGW-packages/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:83
#12 0x000000000040131c in __tmainCRTStartup ()
    at E:/GitHub/MINGW-packages/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:329
#13 0x00000000004014c9 in mainCRTStartup ()
    at E:/GitHub/MINGW-packages/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:223

Compiling with -O0 -g -fno-omit-frame-pointer -fno-inline -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -fasynchronous-unwind-tables -fstack-clash-protection have resulted in somewhat longer stack traces, but still nothing to search for.

Even if I stuff the library with unbuffered debug prints nothing appears on the screen - the programs seems to crash before even first global object is constructed. I have used strace (from Git Bash) and verified that the executable loads all correct shared libraries.

I'm looking for anything that could help me debug the issue. Unfortunately this is a Windows-only crash so running this with uftrace or sanitizers is not possible. Using GCC 8.3.1.

Xeverous
  • 973
  • 1
  • 12
  • 25
  • Consider getting rid of *all* singletons (aka glorified global variables). They really are an anti-pattern. – Jesper Juhl Jul 27 '19 at 12:41
  • 1
    True, that's the safest solution but it's not a simple task considering nana is a ~100k LOC library with around 30 global static objects. How even should I refactor it then? Most global objects are handles to OS things like fonts or some internal DLLs, they need to have the lifetime of the whole program. – Xeverous Jul 27 '19 at 12:51
  • Move all static global scope variables into functions. It is hard to guarantee the order of initialization of static storage duration objects in global scope. It is easy to guarantee the order once they are in inside functions. So move global variables into a function (make them static to the function so they are initialized only once and live for the length of the program). Then the function simply returns them as a result. – Martin York Jul 27 '19 at 20:47
  • I have already done this (which required to modify the library) but running into different crash. Will try on linux with sanitizers. – Xeverous Jul 27 '19 at 21:21

1 Answers1

3

The cause of the crash was that the nana library had -static-libgcc -static-libstdc++ in its CMake files as public dependency. The executable and all other libraries had them linked dynamically. Suprisingly, there were no symbol clashes but the standard library code in the executable was corrupted.

Solved by removing these flags from nana's CMake files.

Xeverous
  • 973
  • 1
  • 12
  • 25