如何在使用gdb调试Qt Creator时避免进入库的源文件?

26

我应该如何配置 Qt Creator 和/或 gdb,以便在使用 Qt 库调试我的程序时,调试器可以避免进入 Qt 的源文件?


cdb也有同样的问题,如何处理? - raidsan
4个回答

16
你需要关闭auto-solib-add功能。在正常的gdb提示符下,你需要输入以下命令:
(gdb) set auto-solib-add off

在Qt Creator中,选项->调试器->Gdb下可以指定一个Gdb启动脚本。创建一个包含"set auto-solib-add off"命令的文件,然后将你的Gdb启动脚本设置为该文件。


2
当然不能与静态构建一起使用(因为它在名称中是auto-SOlib-add)。 - Mr. Developerdude
当您希望停止遍历所有(STL)头文件时,这并不起作用。几乎所有的代码都是从头文件编译的。需要一种跳过它们的方法。std::forward (__t=@0x7fffffffccff: false) at /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/11.1.0/../../../../include/c++/11.1.0/bits/move.h:78 78 { return static_cast<_Tp&&>(__t); } - Carlo Wood

3

您想要的功能(由rpg描述)在GDB中不可用,如果实现该功能将会很难使用。

类似但更简单易用的fstep功能被提议用于GDB。给定:

foo((string("Hello") + string(" World!)).c_str());

fstep 命令将跳过当前行上除最后一个调用外的所有调用(因此跳过字符串构造函数 operator+()c_str(),仅进入foo)。

这个功能还未实现,但很可能会在几个月内实现(它对于 C++调试非常有用)。

与此同时,您可以通过设置临时断点来近似实现该功能:

(gdb) list
1       #include <string>
2       #include <iostream>
3       using namespace std;
4
5       void foo(const char *s)
6       {
7         cout << s << endl;
8       }
9
10      int main()
11      {
12        foo((string("Hello") + string(" World!")).c_str());
13        return 0;
14      }
(gdb) b main
Breakpoint 2 at 0x8048901: file t.cc, line 12.
(gdb) run

Breakpoint 1, main () at t.cc:12
12        foo((string("Hello") + string(" World!")).c_str());
(gdb) tb foo
Breakpoint 3 at 0x80488ca: file t.cc, line 7.
(gdb) c
foo (s=0x804a1f4 "Hello World!") at t.cc:7
7         cout << s << endl;
(gdb) q

1
你认为安迪建议仅删除/隐藏库源文件怎么样? - Piotr Dobrogost
1
你可以尝试,但我认为这对你没有好处:GDB仍然会进入你不想要的函数,只是不会显示它们的源代码。可以说,这比你开始使用的还要糟糕。此外,如果您在ELF平台(例如Linux)上,则必须实际删除库标头--编译器将完整路径嵌入可执行文件中(换句话说,修改GDB启动脚本可能会被证明是徒劳的)。 - Employed Russian
@就业:现在是2012年,fstep仍然不是GDB的一部分。有其他的替代方案吗?(或者我可以应用到gdb源代码的补丁吗?)这确实对C++开发来说是必需的。 - nimrodm
1
@nimrodm 这里有一个非常相似的功能请求:http://sourceware.org/bugzilla/show_bug.cgi?id=8287,已经被修复。虽然不是完全的fstep,但你可以在步进时将不感兴趣的函数加入黑名单。 - Employed Russian
4
该命令现在被称为“跳过”,可在gdb 7.4及更高版本中使用。 - nimrodm

1
也许不是这个问题的完美解决方案,但也许可以帮助排除项目所在的目录(例如第三方库、系统头文件(如STL)等)。如果是这样,请查看https://dev59.com/13NA5IYBdhLWcg3wAItP#31629136https://dev59.com/WG025IYBdhLWcg3wGB0n#42721326。前者允许您指定要跳过的目录(及其所有子目录),以便在运行GDB时进行更改,但需要构建GDB。后者允许在运行GDB之前预设相同的功能,并且不需要构建GDB。

1

评论澄清后更新:

在gdb中,您可以指定搜索哪些源目录 - 如果找不到它们,它就无法进入它们。

为了让gdb进入qt库的源文件,它必须知道它们在哪里 - 很可能是qt-creator在启动调试器时告诉gdb它们在哪里。在qt-creator周围寻找gdb启动脚本 - 它们可能在其中指定。

如果它们没有在启动脚本中指定,并且是gdb自己找到源文件,您应该能够修改gdb启动脚本以使用directory命令清除任何目录(有关语法等,请参见上面的链接)

您还可以通过转到“调试 -> 视图 -> Gdb”来查看gdb控制台,以获取有关它当前正在使用哪些源目录的信息,并手动清除任何目录,如果您想逐个案例执行此操作。


这是我认为Piotr想要的:你有一个像foo(QVariant::fromValue(MySuperClass(QString("hi %1").arg("Andy"))))这样的调用。当进入调试器时,应该跳过arg、QString构造函数、fromValue调用,只进入MySuperClass和foo。据我所知,Qt Creator无法做到这一点。关于在代码步进时跳过sig/slot机制曾经有过一些讨论,但我不知道他们是否实现了它。 - rpg
1
Andy,你所描述的被称为“步出”和“步过”,在几乎每个调试器中都是可能的。我不想手动地跨越Qt源代码。我希望调试器能够自动地跨越它。rpg在他的评论中是正确的,并且他描述了我所询问的功能。 - Piotr Dobrogost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接