Debugging std::string is weird...?

Dear Dev-Team

Ok this question is not a really dev-question, but I more seeking for some hints:

I have some troubles getting lldb to show me a correct string output in a CefSchemeHandlerFactory

https://github.com/gabyx/ExecutionGraph/blob/a24f4c1b538edd6b138503fb96db6fbd71c3b1c5/gui/executionGraphGui/cefapp/FileSchemeHandlerFactory.cpp#L31

When I debug this application built with clang-5.0.1 (llvm install with brew) with the debugger lldb:

** *[ 96%] Building CXX object gui/executionGraphGui/CMakeFiles/ExecutionGraphGUI.dir/cefapp/FileSchemeHandlerFactory.cpp.o* */usr/local/opt/llvm/bin/clang++ -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/gui/executionGraphGui -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/include -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/build/include -I/usr/local/include/eigen3 -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/build/src/meta/include -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/build/external/args-src -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/build/external/cefbinaries-src -I/Users/gabrielnuetzi/Desktop/ExecutionGraph/build/external/cefbinaries-src/include -g -arch x86_64 -mmacosx-version-min=10.9 -std=c++14 -lc++experimental -ferror-limit=50 -Werror=return-type -g -g3 -fno-omit-frame-pointer -Weverything -Wpedantic -Wno-deprecated-register -Wno-documentation -Wno-old-style-cast -Wno-comment -Wno-float-equal -Wno-deprecated -Wno-c++98-compat-pedantic -Wno-undef -Wno-unused-macros -fsanitize=leak -fsanitize=address -o CMakeFiles/ExecutionGraphGUI.dir/cefapp/FileSchemeHandlerFactory.cpp.o -c /Users/gabrielnuetzi/Desktop/ExecutionGraph/gui/executionGraphGui/cefapp/FileSchemeHandlerFactory.cpp* **

I only see really weird output, such as:

[code]
Process 3741 stopped
* thread #22, name = ‘Chrome_IOThread’, stop reason = breakpoint 1.1
frame #0: 0x000000010011eb09 ExecutionGraphGUI`FileSchemeHandlerFactory::Create(this=0x00006060000dc340, scheme_name=0x0000700007ac9c18, request=(ptr_ = 0x0000700007ac9c10)) at FileSchemeHandlerFactory.cpp:37
34 {
35 ++itC;
36 }
→ 37 std::path url(itC, temp.end());
38 // e.g. url : “host/folderA/folderB/file.ext”"
39
40 // Split urlPrefix from front (e.g “host/folderA”)

Process 3741 launched: ‘/Users/gabrielnuetzi/Desktop/ExecutionGraph/build/gui/executionGraphGui/Debug/ExecutionGraphGUI.app/Contents/MacOS/ExecutionGraphGUI’ (x86_64)
(lldb) fr v temp
(std::__1::string) temp = “\x85\xac\a\0p\0\0\x10\x85\xac\a\0p\0\0�\a\0p\0\0\xa0\x83\xac\a\0p\0\0`\x83\xac\a\0p\0\0@”
[/code]

Why is this, or where could the problem be? I have a really hard time to figure out why I cannot successfully debug these strings in my application.
The above example has been done by launching lldb from the terminal. (No python formatters have been loaded I think…? at least not by me)
In a normal main.cpp Application like the one here: https://github.com/gabyx/ExecutionGraph/blob/devGUI/gui/testDebugger/build.sh
everything works and the strings are formatted normally.

Any help really welcome!
BR

Gabriel Nützi
MSc ETH Mechanical Engineering

gnuetzi@gmail.com
+41 (0) 77 424 86 45

You can do a:

(lldb) frame var --raw temp

It will show you the internals of the std::string. If the string is over 22 characters, one of the items in the raw std::string should point to the buffer and the length should be contained inside there as well. The value you see is due to a special summary plug-in that is extracting the std::string value from the innards of the STL implementation.

So a few things could be wrong:
1 - compiler’s location for the variable could be wrong (optimizations?) so we show the wrong value
2 - your STL is newer and might pull some tricks when storing the string and our summary extracting code is doing the wrong thing for your std:string. Many std::string implementations will store up to twenty some character inlined into the std::string itself when the string is short. Maybe we aren’t handling that quite correctly. What is the actual length of your std::string named “temp”?

As a work around, try to run an expression to get the “const char *”
(lldb) p temp.c_str()

See if this pointer is the output of the “frame var --raw temp” command. Also to see if the string value is inlined you can do:

(lldb) p &temp
(lldb) p sizeof(temp)

Then see if the “const char *” value from “p temp.c_str()” falls between the “&temp” and “&temp + sizeof(temp)”.

Let me know what you find. My guess is we might not be handling special cases when the string is inlined, but that is just a guess.

Greg Clayton

Thanks a lot Greg!
This helps alot, at the moment of reading I have already solved the issue.

clang 5.0.1 makes something wrong when using -fsanitize=address, with clang 7.0 everything is ok!!
I have spent alot of time making sure the right standart lib is linked/loaded, it was the case I think…

I will have a look later on your very good suggestions! (I am quite a newbie with lldb) :slight_smile:

Gabriel

The address sanitizer does quite a number of code transformations, and if any of these transformations moves a variable to a different location, the debug information has to be fixed as well. There were a bugs in this part of the sanitizer in its original version, many of which have been fixed. That's likely why 5.0.1 had problems you didn't see in 7.0. If you see any more bad variable printing in the debugger that only show up with this or other sanitizers on, please file them with llvm.org bug tracker (http://bugs.llvm.org).

Jim