g ++(GCC)5.2.0
clang版本3.7.1(标签/ RELEASE_371/final)
GNU gdb(GDB)7.12
由于某种原因,当使用clang编译时,Gdb无法找到std :: string的定义.我有自定义编译和构建gcc和clang,因为Centos 6.5附带了旧版本的gcc.
示例代码
#include <string>
int main()
{
std::string s("This is a string");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用g ++编译和调试 - 工作得很好
[~]$ 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)
Run Code Online (Sandbox Code Playgroud)
检查它是否与我的rpm构建版本的libstdc ++链接,而不是系统
[~]$ 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
Run Code Online (Sandbox Code Playgroud)
如果我用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)
Run Code Online (Sandbox Code Playgroud)
现在我得到了一个不完整的类型 - 但是正在使用相同的库
[~]$ 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
Run Code Online (Sandbox Code Playgroud)
有没有人有任何关于在哪里寻找或我错过的东西的建议.两个编译器在构建时都是自举的 - 一切看起来都很好 - 它似乎是std :: string在使用clang时没有定义.
小智 14
正如ks1322所提到的,这是因为clang决定不为libstc ++发出调试信息.
你可以通过提供以下标志强制clang这样做:
-D_GLIBCXX_DEBUG
我只提供调试版本的标志,但如果debug是默认值,而版本版本是特殊目标,则应删除它:
release: CXXFLAGS := $(filter-out -D_GLIBCXX_DEBUG,$(CXXFLAGS)) -O2
Run Code Online (Sandbox Code Playgroud)
这为我解决了同样的问题.
Jul*_*fin 11
由 ks1322 链接的 bug 24202 中提到的最后一个解决方法值得一看:
-fno-limit-debug-info 将使您的调试信息更大,链接速度较慢(如果您不使用 -gsplit-dwarf)和调试器性能。但是,是的,会解决这个问题。
使用-fno-limit-debug-info
强制 Clang 以更大的二进制文件为代价为例如 std::string 发出调试信息,同时保持与其他库和系统/SDK 其余部分的兼容性。
正如 ks1322 和 Kevin 提到的,人们可以改为使用-D_GLIBCXX_DEBUG
将 libstdc++ 切换到调试模式,但这代价很高:您链接的任何库以及与您交换 STL 容器(字符串、向量等)的任何库也必须使用-D_GLIBCXX_DEBUG
. 意思是:您的系统/SDK 必须使用一组单独的库来支持它,否则您必须自己重建它们。
我在 Fedora 上用 system clang 重现了这个问题。
似乎 clang 没有发出调试信息,std::string
因为它被告知libstdc++
提供了它。请参阅错误 24202 中的此评论:
看起来您没有安装 libstdc++ 的调试信息:
缺少单独的调试信息,使用:dnf debuginfo-install libgcc-5.1.1-4.fc22.x86_64 libstdc++-5.1.1-4.fc22.x86_64
Clang 没有为 std::string 发出调试信息,因为它被告知 libstdc++ 提供了它(但在你的情况下,它没有安装);这是 GCC 显然没有执行的调试大小优化。
如果您为 libstdc++ 安装调试信息,这是否有效?
我已经为libstdc++
with 命令安装了调试信息dnf debuginfo-install libstdc++-6.2.1-2.fc25.x86_64
并解决了这个问题。
clang 相信 libstd++ 的调试符号可用,因此您必须安装它们。请参阅 ks1322 的答案,了解如何在 Fedora 上执行此操作。在 Ubuntu 上,运行:
sudo apt-get install libstdc++6-dbgsym
Run Code Online (Sandbox Code Playgroud)
之后,事情就会正常进行。
不要定义,_GLIBCXX_DEBUG
因为这会破坏 libstdc++ 的 abi。
-fno-limit-debug-info
将使 clang 发出比必要的更大的调试信息,所以我也建议不要这样做。只需安装 libstdc++ 的调试信息包即可。