GDB C++ 出错时无法获取源核心行(分段错误)

Posted

技术标签:

【中文标题】GDB C++ 出错时无法获取源核心行(分段错误)【英文标题】:GDB C++ Not possible to get source core line when error (Segmentation Fault) 【发布时间】:2021-01-15 22:09:28 【问题描述】:

我有几天时间处理分段错误错误,但我无法找到它。我正在使用 gdb 对其进行调试,但 GDB 没有给我任何关于发生错误的行的详细信息。

现在,我生成一个错误只是为了确保我的构建与 GDB 兼容。我正在使用启用了 degub 的 cmake 进行编译:cmake -DCMAKE_BUILD_TYPE=Debug .. 并且我还确保在 CMakeFiles/SmartGate.dir/flags.make 中启用了 -g 标志,并且我手动添加了 -ggdb 标志。

我使用make VERBOSE=1 SmartGate 来确保编译和链接过程中存在标志,它们确实存在。

我可以在 gdb 中加载我的构建:

GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "armv7l-unknown-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) file  SmartGate
Reading symbols from SmartGate...

而且我还能够显示存在注入错误的源代码:

(gdb) l SmartGate.cpp:30
25      sqlite3 *db;
26  
27      std::string tmp_db = NULL;//"controller_test_data.db";
28      int rc = sqlite3_open(tmp_db.c_str(), &db);
29      if (rc)
30      
31          spdlog::error("Can't open database: ", sqlite3_errmsg(db));
32          sqlite3_close(db);
33          exit(1);
34      
(gdb) 

但是当错误发生时,我只得到以下回溯:

(gdb) r
Starting program: /home/pi/SmartGate/build/SmartGate 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
[New Thread 0xab33a1e0 (LWP 12870)]
[New Thread 0xaa2591e0 (LWP 12871)]
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid

Thread 1 "SmartGate" received signal SIGABRT, Aborted.
0xb3e3ef24 in raise () from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) bt
#0  0xb3e3ef24 in raise () from /lib/arm-linux-gnueabihf/libc.so.6
#1  0xb3e2a230 in abort () from /lib/arm-linux-gnueabihf/libc.so.6
#2  0x00000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

这是我要跟踪的实际错误的错误输出:

Thread 1 "SmartGate" received signal SIGSEGV, Segmentation fault.
0xb6fb9c1c in memcpy () from /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so
(gdb) bt
#0  0xb6fb9c1c in memcpy () from /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so
#1  0x00000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

有什么建议吗?

【问题讨论】:

你试过在abort 上设置断点吗?通过这样做(在 Windows 上),我得到了一个很好的堆栈跟踪 @Jean-FrançoisFabre,中止错误只是没有错误来源的输出示例。您对 SIGSEGV 有什么建议吗? 看起来堆栈已损坏。您别无选择,只能尝试查找触发此操作的操作(使用“打印”跟踪并逐行逐行,并留出一些时间) 【参考方案1】:

您的问题是关于从分段错误中展开的,但您的示例是关于从abort() 展开的。这些是完全不同的事情(换句话说,关于您的人为示例的问题的答案不太可能对您的实际问题有所帮助)。

terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_M_construct null not valid 我只得到以下回溯:

这里发生了什么:

    您的代码调用相当于std::string foo(nullptr); std::string 构造函数在你的程序中检测到这个错误并抛出异常 由于您没有 catch 块,因此会调用 std::terminate(),这 最终调用abort() GDB 无法将堆栈展开到调用 abort() 的位置。

有几种方法可以避免从abort() 展开堆栈。

    审核程序中构造新std::string 实例的位置,确保它们都没有将nullptr 作为参数传递。 在std::string::string(const char *s) 构造函数上设置断点。使其以s == NULL 为条件。 当使用catch throw 命令抛出异常时,要求 GDB 停止。 Documentation。 您可以使用调试信息重建您的libc.so.6,或从您的发行版安装libc6-dbg 或类似的软件包。这可能帮助 GDB 从abort() 中解脱出来。

【讨论】:

正如我在帖子中提到的。这是一个注入错误。如果您检查代码,则字符串的正确输入会在 NULL 值旁边注释。 @MiguelResendiz 是的,我知道。请阅读答案的第一个和最后一个陈述。

以上是关于GDB C++ 出错时无法获取源核心行(分段错误)的主要内容,如果未能解决你的问题,请参考以下文章

从核心转储中获取堆栈跟踪

分析分段错误核心转储 (gdb)

运行我的代码时出现分段错误(核心转储)问题

分段错误 - 如何调试? [关闭]

为啥使用 gdb 启动 C++ 程序时出现分段错误?

c++:分段错误(核心转储)