Cannot view std::string when compiled with clang
Asked Answered
S

5

29

g++ (GCC) 5.2.0

clang version 3.7.1 (tags/RELEASE_371/final)

GNU gdb (GDB) 7.12

Gdb is unable to locate the definition of std::string when compiled with clang for some reason. I have custom compiled and build gcc and clang as Centos 6.5 comes with older version of gcc.

Example code

#include <string>

int main()
{
    std::string s("This is a string");

    return 0;
}

Compile with g++ and debug - works just fine

[~]$ g++ -ggdb3 -std=c++14 stl.cpp 
[~]$ gdb a.out
GNU gdb (GDB) 7.12
Reading symbols from a.out...done.
(gdb) break main
Breakpoint 1 at 0x400841: file stl.cpp, line 5.
(gdb) r
Starting program: /home/vagrant/a.out 

Breakpoint 1, main () at stl.cpp:5
5       std::string s("This is a string");
(gdb) n
7       return 0;
(gdb) p s
$1 = {static npos = <optimized out>, 
  _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x612c20 "This is a string"}, _M_string_length = 16, {
    _M_local_buf = "\020\000\000\000\000\000\000\000\300\b@\000\000\000\000", _M_allocated_capacity = 16}}
(gdb) 

Check that it is linking with my rpm build version of libstdc++ and not system

[~]$ ldd a.out
    linux-vdso.so.1 =>  (0x00007ffd709e0000)
    libstdc++.so.6 => /opt/spotx-gcc/lib64/libstdc++.so.6 (0x00007f29318fa000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f2931676000)
    libgcc_s.so.1 => /opt/spotx-gcc/lib64/libgcc_s.so.1 (0x00007f293145f000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f29310cb000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f2931c93000)

[~]$ objdump -T -C a.out
a.out:     file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __libc_start_main
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4.21 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4 std::allocator<char>::~allocator()
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4.21 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4 std::allocator<char>::allocator()
0000000000000000      DF *UND*  0000000000000000  GCC_3.0     _Unwind_Resume
0000000000400700      DF *UND*  0000000000000000  CXXABI_1.3  __gxx_personality_v0

All looks good now if I try the same with clang

[~]$ clang++ -std=c++14 -g stl.cpp
[~]$ gdb a.out
GNU gdb (GDB) 7.12
Reading symbols from a.out...done.
(gdb) break  main
Breakpoint 1 at 0x400853: file stl.cpp, line 5.
(gdb) r
Starting program: /home/vagrant/a.out 

Breakpoint 1, main () at stl.cpp:5
5       std::string s("This is a string");
(gdb) n
7       return 0;
(gdb) p s
$1 = <incomplete type>
(gdb) 

Now I get an incomplete type - but the same libraries are being used

[~]$ ldd a.out
    linux-vdso.so.1 =>  (0x00007fff5352d000)
    libstdc++.so.6 => /opt/spotx-gcc/lib64/libstdc++.so.6 (0x00007f76b4023000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f76b3d9f000)
    libgcc_s.so.1 => /opt/spotx-gcc/lib64/libgcc_s.so.1 (0x00007f76b3b88000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f76b37f4000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f76b43bc000)


[~]$ objdump -T -C a.out
a.out:     file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __libc_start_main
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4.21 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4 std::allocator<char>::~allocator()
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4.21 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
0000000000000000      DF *UND*  0000000000000000  GLIBCXX_3.4 std::allocator<char>::allocator()
0000000000000000      DF *UND*  0000000000000000  GCC_3.0     _Unwind_Resume
0000000000400700      DF *UND*  0000000000000000  CXXABI_1.3  __gxx_personality_v0

Does anyone have any advice on where to look or something that I've missed. Both compilers are bootstrapped when building them - everything seems fine - it just appears to be std::string is not defined when using clang.

Sedentary answered 19/1, 2017 at 15:24 Comment(0)
W
29

As ks1322 mentioned, this is because clang has decided not to emit debug information for libstc++.

You can force clang to do so by providing the following flag: -D_GLIBCXX_DEBUG

I would only provide the flag for debug builds, but if debug is the default and release builds are a special target you should remove it:

release: CXXFLAGS := $(filter-out -D_GLIBCXX_DEBUG,$(CXXFLAGS)) -O2

This has fixed the same problem for me.

Wyant answered 23/6, 2017 at 18:2 Comment(3)
Although this works keep in mind that _GLIBCXX_DEBUG actually changes the ABI, so if you're linking to libraries that were built without the define you will get linker errors.Destinee
It should be CPPFLAGS because these belong with the preprocessor (aka CPP), not the compiler. And yes, it makes a difference in every well-formed GNUmakefile which taps sufficiently into and reuses the built-in rules.Baalbek
Can be enabled for CMake with -DCMAKE_CXX_FLAGS=-D_GLIBCXX_DEBUG from the CLI.Lysine
S
19

The last workaround mentioned in bug 24202 as linked by ks1322 is worth having a look at:

-fno-limit-debug-info will make your debug info larger, slow link (if you're not using -gsplit-dwarf) and debugger performance. But, yes, will address this.

Using -fno-limit-debug-info forces Clang to emit debug information for e.g. std::string at the cost of a larger binary while preserving compatibility with other libraries and the rest of the system/SDK.

As ks1322 and Kevin mentioned, one can instead use -D_GLIBCXX_DEBUG to switch libstdc++ into debug mode but this comes at a heavy price: any library you link against and with which you exchange STL containers (string, vector, etc.) must also be built with -D_GLIBCXX_DEBUG. Meaning: your system/SDK must either support this with a separate set of libraries or you will have to rebuild them yourself.

Spittle answered 23/10, 2019 at 16:35 Comment(2)
Thanks !! that fixed the problem for me while using CLion :)Marla
I added -fno-limit-debug-info by editing CMakeCache, then recompiled, and it worked. How do I make this happen when running CMake for the first time?Tonguetied
A
5

I've reproduced this issue on Fedora with system clang.

It appears that clang is not emitting debug information for std::string because it was told that libstdc++ provides it. See this comment from bug 24202:

Looks like you don't have debug information for libstdc++ installed:

Missing separate debuginfos, use: dnf debuginfo-install libgcc-5.1.1-4.fc22.x86_64 libstdc++-5.1.1-4.fc22.x86_64

Clang is not emitting debug information for std::string because it was told that libstdc++ provides it (but in your case, it's not installed); this is a debug size optimization that GCC apparently doesn't perform.

Does this work if you install the debug information for libstdc++?

I've installed debug info for libstdc++ with command dnf debuginfo-install libstdc++-6.2.1-2.fc25.x86_64 and that resolved the issue.

Alveraalverez answered 3/2, 2017 at 18:52 Comment(1)
I built gcc as well as an RPM. Installing the debug package that rpmbuild creates for gcc makes no difference to this, but gives me somewhere to look. Probably need to recompile gcc with a flagSedentary
T
5

clang trusts that debugging symbols for libstd++ are available, so you have to install them. See ks1322's answer for how to do that on Fedora. On Ubuntu, run:

sudo apt-get install libstdc++6-dbgsym

After that, things will just work.

Do not define _GLIBCXX_DEBUG since that'll break libstdc++'s abi.

-fno-limit-debug-info will make clang emit debug info that's larger than necessary, so I'd advise against that too. Just install the debug info package for libstdc++.

Tameshatamez answered 4/1, 2021 at 16:10 Comment(4)
I get "E: Unable to locate package libstdc++6-dbgsym E: Couldn't find any package by regex 'libstdc++6-dbgsym'"Entryway
@Entryway on Debian-derived distros I suggest you use something like apt-cache search libstdc++|awk '$1 ~ /-dbgsym$/ {print}' to find out what's available. Have you prepared your system so APT will look for ddebs?Baalbek
I already have libstdc++6-11-dbg and I still have this problem. Adding the dbgsym repositories and Installing the libstdc++6-dbgsym package instead, solved the problem though. Maybe a version mismatch problem.Horizon
Does anyone know how to install libstdc++6-dbgsym for Ubuntu18.04. I've tried adding ddebs list to my sources.list.d, but I'm still unable to find that package when I list available packages with sudo apt listWare
S
3

for me: -fno-limit-debug-info is the real solution for clang / clion. _GLIBCXX_DEBUG cause link error with some library

clang version 10.0.0-4ubuntu1 Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin

CLion 2022.1.3 Build #CL-221.5921.27, built on June 21, 2022

Sub answered 11/9, 2022 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.