jeremy-rifkin / cpptrace

Simple, portable, and self-contained stacktrace library for C++11 and newer
MIT License
621 stars 64 forks source link

Issue with null characters in string returned by cpptrace exceptions #113

Closed dsafa closed 4 months ago

dsafa commented 4 months ago

Hello, I'm encountering issues with printing out the stack trace due to null characters being in the stack trace strings in the cpptrace exceptions. This is only really an issue because I am just catching the base std::exception and printing out exception::what() which causes the message to get cut off.

For example,

    try {
        throw cpptrace::logic_error("test");
    }
    catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }

Results in output like this

Stack trace (most recent call first):
#0 0x

when the expected output should be like this

Stack trace (most recent call first):
#0 0x0007ff67ef1b4b00 in main() at...

I debugged it and I've narrowed it down to this format which eventually calls this Since the while loop won't necessarily iterate all n_digits times, the front of the number string is left alone with \0 values

Info OS: Windows 11 64bit Compiled with msvc

jeremy-rifkin commented 4 months ago

Thank you, that’s definitely a bug. I will investigate asap.

jeremy-rifkin commented 4 months ago

Was 0x0007ff67ef1b4b00 the actual value causing the improper format? It should always loop n_digits times and I tried to test that extensively but it's possible I missed something, or maybe it's too late at night to think about such things

dsafa commented 4 months ago

yeah I was pretty light on details. I've got an updated setup so I can give better details

setup I just got the latest branch and just built and ran it with visual studio as x64-debug.

I've modified the demo.cpp as this:

int main() {
    auto str = cpptrace::generate_trace().to_string();

    std::cout << str.c_str() << std::endl;
    std::cout << str << std::endl;
}

outputs:

Stack trace (most recent call first):
#0 0x
Stack trace (most recent call first):
#0 0x7ff745f7b487 in main() at C:\source\cpptrace-main\test\demo.cpp:36
#1 0x7ff745ff61f8 in invoke_main() at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
#2 0x7ff745ff609d in __scrt_common_main_seh() at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#3 0x7ff745ff5f5d in __scrt_common_main() at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
#4 0x7ff745ff628d in mainCRTStartup(void*) at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
#5 0x7ffc65b0257c in BaseThreadInitThunk
#6 0x7ffc67baaa47 in RtlUserThreadStart

Here are the actual values I observe in to_string

passed in: value | 140700007511175 | unsigned __int64 and n_digits | 16 | unsigned __int64

And during the iteration i value
15 140700007511175
14 8793750469448
13 549609404340
12 34350587771
11 2146911735
10 134181983
9 8386373
8 524148
7 32759
6 2047
5 127
4 7

Where the final string becomes "\0\0\0\07ff745f7b487"

and the stack trace:

>   demo.exe!microfmt::detail::to_string<4,15>(unsigned __int64 value, const char * digits) Line 99 C++
    demo.exe!microfmt::detail::to_string(unsigned __int64 value, const microfmt::detail::format_options & options) Line 107 C++
    demo.exe!microfmt::detail::format_value::write(std::string & out, const microfmt::detail::format_options & options) Line 183    C++
    demo.exe!microfmt::detail::format<4>(const char * fmt_begin, const char * fmt_end, std::array<microfmt::detail::format_value,4> args) Line 287  C++
    demo.exe!microfmt::format<char const * const &,unsigned __int64,unsigned __int64 const &,char const * const &>(const char * fmt, const char * const & <args_0>, unsigned __int64 && <args_1>, const unsigned __int64 & <args_2>, const char * const & <args_3>) Line 318    C++
    demo.exe!cpptrace::print_frame(std::basic_ostream<char,std::char_traits<char>> & stream, bool color, unsigned int frame_number_width, unsigned __int64 counter, const cpptrace::stacktrace_frame & frame) Line 169  C++
    demo.exe!cpptrace::stacktrace::print(std::basic_ostream<char,std::char_traits<char>> & stream, bool color, bool newline_at_end, const char * header) Line 203   C++
    demo.exe!cpptrace::stacktrace::to_string(bool color) Line 260   C++
    demo.exe!main() Line 36 C++

I hope that helps

jeremy-rifkin commented 4 months ago

Thank you so much, that’s fantastic. I really appreciate all the help to identify the issue. Knowing it is msvc and seeing n_digits incorrectly computed gives a pretty good idea of where the issue lies!

jeremy-rifkin commented 4 months ago

Thank you again so much, this is now resolved in main and I will release patch version soon

dsafa commented 4 months ago

thanks!