Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

easylogging throw on HeapAlloc during initialization for static build with thread-safe (windows, vcpkg, static, thread-safe) #842

Open
wluter opened this issue Sep 5, 2023 · 5 comments

Comments

@wluter
Copy link

wluter commented Sep 5, 2023

easyloggingpp from vcpkg seems to throw during INITIALIZE_EASYLOGGINGPP when used in a static build on Windows with thread-safe feature enabled. The error involves heap allocation.

It is a 64 bit MFC application on windows with static build and uses vcpkg for several components including easyloggingpp

Stack Trace:
ntdll.dll!00007ffb4eabe414() Unknown
ntdll.dll!00007ffb4eabb44d() Unknown

MyApp.exe!heap_alloc_dbg_internal(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Line 359 C++
MyApp.exe!heap_alloc_dbg(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Line 450 C++
MyApp.exe!_malloc_dbg(unsigned __int64 size, int block_use, const char * file_name, int line_number) Line 496 C++
MyApp.exe!operator new(unsigned __int64 nSize) Line 43 C++
MyApp.exe!std::_Default_allocate_traits::_Allocate(const unsigned __int64 _Bytes) Line 88 C++
MyApp.exe!std::_Allocate<16,std::_Default_allocate_traits,0>(const unsigned __int64 _Bytes) Line 245 C++
MyApp.exe!std::allocator<std::_List_node<std::pair<enum el::Level const ,el::base::LogFormat>,void *>>::allocate(const unsigned __int64 _Count) Line 975 C++
MyApp.exe!std::_Alloc_construct_ptr<std::allocator<std::_List_node<std::pair<enum el::Level const ,el::base::LogFormat>,void *>>>::_Allocate() Line 1152 C++
MyApp.exe!std::_List_node_emplace_op2<std::allocator<std::_List_node<std::pair<enum el::Level const ,el::base::LogFormat>,void *>>>::_List_node_emplace_op2<std::allocator<std::_List_node<std::pair<enum el::Level const ,el::base::LogFormat>,void >>><std::pair<enum el::Level,el::base::LogFormat>>(std::allocator<std::_List_node<std::pair<enum el::Level const ,el::base::LogFormat>,void >> & Al, std::pair<enum el::Level,el::base::LogFormat> && <_Vals_0>) Line 586 C++
MyApp.exe!std::_Hash<std::_Umap_traits<enum el::Level,el::base::LogFormat,std::_Uhash_compare<enum el::Level,std::hash,std::equal_to>,std::allocator<std::pair<enum el::Level const ,el::base::LogFormat>>,0>>::emplace<std::pair<enum el::Level,el::base::LogFormat>>(std::pair<enum el::Level,el::base::LogFormat> && <_Vals_0>) Line 613 C++
MyApp.exe!std::unordered_map<enum el::Level,el::base::LogFormat,std::hash,std::equal_to,std::allocator<std::pair<enum el::Level const ,el::base::LogFormat>>>::insert<std::pair<enum el::Level,el::base::LogFormat>,0>(std::pair<enum el::Level,el::base::LogFormat> && _Val) Line 276 C++
MyApp.exe!el::base::TypedConfigurations::setValueel::base::LogFormat(el::Level level, const el::base::LogFormat & value, std::unordered_map<enum el::Level,el::base::LogFormat,std::hash,std::equal_to,std::allocator<std::pair<enum el::Level const ,el::base::LogFormat>>> * confMap, bool includeGlobalLevel) Line 2018 C++
MyApp.exe!el::base::TypedConfigurations::build(el::Configurations * configurations) Line 1697 C++
MyApp.exe!el::base::TypedConfigurations::TypedConfigurations(el::Configurations * configurations, std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<std::basic_fstream<char,std::char_traits>>,std::hashstd::string,std::equal_tostd::string,std::allocator<std::pair<std::string const ,std::shared_ptr<std::basic_fstream<char,std::char_traits>>>>>> logStreamsReference) Line 1621 C++
MyApp.exe!el::Logger::configure(const el::Configurations & configurations) Line 661 C++
MyApp.exe!el::Logger::Logger(const std::string & id, const el::Configurations & configurations, std::shared_ptr<std::unordered_map<std::string,std::shared_ptr<std::basic_fstream<char,std::char_traits>>,std::hashstd::string,std::equal_tostd::string,std::allocator<std::pair<std::string const ,std::shared_ptr<std::basic_fstream<char,std::char_traits>>>>>> logStreamsReference) Line 619 C++
MyApp.exe!el::base::RegisteredLoggers::get(const std::string & id, bool forceCreation) Line 1900 C++
MyApp.exe!el::base::Storage::Storage(const std::shared_ptrel::LogBuilder & defaultLogBuilder) Line 2079 C++
MyApp.exe!el::base::`dynamic initializer for 'elStorage''() Line 19 C++
MyApp.exe!_initterm(void(
)() * first, void(
)() * last) Line 22 C++
MyApp.exe!__scrt_common_main_seh() Line 258 C++
MyApp.exe!__scrt_common_main() Line 331 C++
MyApp.exe!wWinMainCRTStartup(void * __formal) Line 17 C++
kernel32.dll!00007ffb4e4e7614() Unknown
ntdll.dll!00007ffb4eae26f1() Unknown

@wluter
Copy link
Author

wluter commented Sep 6, 2023

I have a minimal project ready to demonstrate the problem. Some additional notes:

  1. If you compile static with a vcpkg manifest file using no features it compiles, easylogging initializes, and it runs but will eventually crash if you log from multiple threads.
  2. If you enable feature no-defaultfile it will not initialize
  3. If you enable thread-safe it will not initialize
  4. Because MFC application does not expose main() then INITIALIZE_EASYLOGGING must be put in the cpp of the CWinApp derived application class where InitInstance is called. Maybe this is the problem?

@wluter
Copy link
Author

wluter commented Sep 8, 2023

Further reading and debugging indicates this may be due to it being a static compilation. The actual HeapAlloc error occurs during creation of el::base::Storage.

To debug I replaced INITIALIZE_EASYLOGGINGPP AS FOLLOWS:
//INITIALIZE_EASYLOGGINGPP namespace el { namespace base { el::base::type::StoragePointer elStorage; } el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); }
And put this at the begging of main:
el::base::DefaultLogBuilder* dlb = new el::base::DefaultLogBuilder(); el::LogBuilderPtr lpb(dlb); el::base::Storage * s = new el::base::Storage(lpb); //<<< FAILS HERE el::base::elStorage.reset(s); START_EASYLOGGINGPP(argc, argv);

And the trace shows it fails in Logger* RegisteredLoggers::get

@impromptu1583
Copy link

I also have this issue. @wluter did you ever find a solution?

@wluter
Copy link
Author

wluter commented Jun 2, 2024

I also have this issue. @wluter did you ever find a solution?

I did not. I ran out of time trying so I moved on to use g3log instead. I have had tremendous success with it so I have abandoned easyloggingpp. NOTE: if you need multiple log files then g3log is more work - it has a single stream sink and you have to create your own sinks for multiple log files.

@impromptu1583
Copy link

Thank you so much! I'll give g3log a try!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants