Closed gdeankrotos closed 1 month ago
Hi @gdeankrotos!
I'm interested if std::string c_str is supported here. In my application we use a library with it's own String object, so we use std::string as an intermediary to get to c_str.
The allocation stack trace is as follows:
> SentryTest.exe!operator new(unsigned __int64 size) Line 36 C++ SentryTest.exe!std::_Default_allocate_traits::_Allocate(const unsigned __int64 _Bytes) Line 102 C++ SentryTest.exe!std::_Allocate<16,std::_Default_allocate_traits>(const unsigned __int64 _Bytes) Line 227 C++ SentryTest.exe!std::allocator<std::_Container_proxy>::allocate(const unsigned __int64 _Count) Line 955 C++ SentryTest.exe!std::_Container_proxy_ptr12<std::allocator<std::_Container_proxy>>::_Container_proxy_ptr12<std::allocator<std::_Container_proxy>>(std::allocator<std::_Container_proxy> & _Al_, std::_Container_base12 & _Mycont) Line 1447 C++ SentryTest.exe!std::string::_Construct<1,char const *>(const char * const _Arg, const unsigned __int64 _Count) Line 868 C++ SentryTest.exe!std::string::basic_string<char,std::char_traits<char>,std::allocator<char>>(const char * const _Ptr) Line 750 C++ SentryTest.exe!main() Line 22 C++
Yes, the usage of std::string.c_str()
is supported since it only returns a pointer to a NULL
-terminated C string. However, we never take ownership of any strings (because, like in this example, you wouldn't want us to rely on the lifetime of client strings or even free them before).
So what happens here is that when we get your pointer to the string, we immediately clone the entire string it points to before assigning it to our internal structs. sentry_close()
will then free the internal clone, leaving your std::string
untouched. The stack trace shows a new
initiated in your main, seemingly still allocated (not surprising, given RAII
) but not owned by the Native SDK.
Replacing const std::string with char* inline, the string leaks go away, but a leak is still being detected from crashpad_backend_startup, from the following allocation:
SentryTest.exe!operator new(unsigned __int64 size) Line 36 C++ > SentryTest.exe!crashpad::`anonymous namespace'::CommonInProcessInitialization() Line 620 C++ SentryTest.exe!crashpad::CrashpadClient::StartHandler(const base::FilePath & handler, const base::FilePath & database, const base::FilePath & metrics_dir, const std::string & url, const std::string & http_proxy, const std::map<std::string,std::string,std::less<std::string>,std::allocator<std::pair<std::string const ,std::string>>> & annotations, const std::vector<std::string,std::allocator<std::string>> & arguments, bool restartable, bool asynchronous_start, const std::vector<base::FilePath,std::allocator<base::FilePath>> & attachments) Line 660 C++ SentryTest.exe!crashpad_backend_startup(sentry_backend_s * backend, const sentry_options_s * options) Line 442 C++ SentryTest.exe!sentry_init(sentry_options_s * options) Line 153 C SentryTest.exe!main() Line 23 C++
Conversely, this is an actual leak because the crashpad
client doesn't provide any mechanism to deallocate its client state. Once we initialize the crashpad
backend, the client will stay allocated until the process exits. Given that its primary usage is the detection of unwanted process exits, this is a fair trade-off. This also means the crashpad
crash handler remains active beyond sentry_close()
(on macOS and Windows), meaning that if your application crashes after sentry_close()
, the crash will still be reported.
Thank you for the quick response @supervacuus, I'm glad to hear that the residing leak is expected there.
I spent a bit more time investigating the string issue and I think I've got to the bottom of it.
In my application, the leaking memory was always a file path. I noticed that sentry__path_from_str_n
determines the size of the destination using sizeof(wchar_t)
, but wchar_t is different between Windows and unix platforms.
Long story short, I found the method sentry_options_set_handler_pathw
already exists to solve this exact problem.
I'm now just passing a wchar*
directly to the source string, skipping std::string altogether. This has fixed the leak.
Thanks again!
Sentry 0.7.10, MSVC 14.41.34120
I have been encountering leaks reported by the CRT debugger which trace back to sentry, specifically initialisation and shutdown.
Take the following test program:
The output is as follows:
I'm interested if std::string c_str is supported here. In my application we use a library with it's own String object, so we use std::string as an intermediary to get to c_str.
The allocation stack trace is as follows:
Replacing const std::string with char* inline, the string leaks go away, but a leak is still being detected from crashpad_backend_startup, from the following allocation:
Any insight into this would be much appreciated!