nana: crash on Windows upon startup

Hello, I’m trying to run any of the examples but all crash on startup.

Minimal code:

#include <nana/gui/wvl.hpp>
#include <nana/gui/widgets/label.hpp>
int main()
{
    using namespace nana;
    form    fm;
    label   lb(fm, rectangle(fm.size()));
    lb.caption("Hello, World");
    fm.show();
    exec();
}

GDB backtrace:

#0  0x00007ffd430fe912 in ntdll!RtlCallEnclaveReturn ()
   from C:\Windows\SYSTEM32\ntdll.dll
#1  0x00007ffd4306bbce in ntdll!RtlRaiseException ()
   from C:\Windows\SYSTEM32\ntdll.dll
#2  0x00007ffd3f9aa388 in RaiseException ()
   from C:\Windows\System32\KernelBase.dll
#3  0x000000006144d711 in ?? ()
   from [...] libgcc_s_seh-1.dll
#4  0x000000006fd070c5 in ?? ()
   from [...] libstdc++-6.dll
#5  0x000000006fcfb1d7 in ?? ()
   from [...] libstdc++-6.dll
#6  0x0000000000405694 in void std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_construct<wchar_t const*>(wchar_t const*, wchar_t const*, std::forward_iterator_tag) [clone .constprop.292] ()
#7  0x000000000040a512 in nana::to_utf8[abi:cxx11](std::basic_string_view<wchar_t, std::char_traits<wchar_t> >) ()
#8  0x000000000040a981 in nana::font_factory(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, nana::detail::font_style const&, std::filesystem::__cxx11::path) ()
#9  0x0000000000110bfa in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Comments: 45 (36 by maintainers)

Most upvoted comments

Regarding PR for CMake files:

  • There should be 2 separate options:
    • BUILD_SHARED_LIBS - build nana as shared/static - this already exists and is OK (every CMake project has such option)
    • NANA_SHARED_STDLIB - use shared/static standard library - there is no such option and it should be added

Some other info for you:

https://github.com/cnjinhao/nana/blob/38cdf4779456ba697d7da863f7c623e25d30f650/build/cmake/shared_libs.cmake#L38

CMAKE_COMPILER_IS_GNUCXX is true for MinGW, you can remove “# AND NOT MINGW??”

https://github.com/cnjinhao/nana/blob/38cdf4779456ba697d7da863f7c623e25d30f650/build/cmake/shared_libs.cmake#L40-L41

This is unneded, GCC and Clang automatically add standard library to every executable. It works the other way: you need to add -nostdlib to not link standard library.

I can make a PR for all of this.

Is nana doing anything related to Windows input/output API?

This code:

#include <iostream>

int main()
{
    std::cerr << "entered main" << std::endl;
}

Just can not crash, but when linked to nana library I get a crash, inside std::endl:

#0  0x00000000004a51ac in std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) ()
#1  0x00000000004aa42e in main ()

The program’s output is exactly entered mainSegmentation fault (no endline). When the program is not linked to nana, it does not crash.

This is an compiler issue.

It’s not a compiler issue. The compiler is not allowed to remove the global object. But what the linker does is outside the standard. Linker removes the object because it’s never used.

If we are trying to make workaround for the issue, it is hard to guarantee the workaround work correctly.

False. There is no workaround - we don’t go around any compiler/linker bug. The linker removes the object because it is not used - nothing in the example uses platform spec object (only side effects of it’s construction). The workaround is using specific flags like --whole-archive to prevent linker from performing all allowed optimizations.

The solution is to make that symbol used. It’s very simple. Changing return *data::storage; to static platform_runtime runtime; return runtime; and changing static platform_spec object to Meyer’s singleton will guuarantee that both objects are constructed and that they are constructed in correct order. This change has no impact on implementation behaviour, it only makes the platform_runtime used which prevents linker from removing it. Both are still static objects, cheaply initialized and avoid race issues.

This is an compiler issue. Without LTO, I never encounter the issue on various compilers(VC, GCC even on raspberry pi and clang). If we are trying to make workaround for the issue, it is hard to guarantee the workaround work correctly. Btw, using a static object to initializing internal objects is much easy and cheap way. It can avoid resource race issue.