要开始使用gdb,短小的示例是很好的。一旦你知道如何运行它(gdb 程序名),如何检查和遍历堆栈(bt, up, down),查看你当前所在的代码(list),以及如何获取变量的值(print),你就具备了处理最常见的崩溃(即段错误)的能力,并且你已经引导自己达到了可以自己学习更多东西的程度。
这是一个示例会话
1 2 3 4 5 6 7 8 9 10 11 12
|
#include<iostream>
using namespace std;
int main()
{
int x = 7;
int *p = 0;
cout << "x = " << x;
cout << "The pointer points to the value " << *p;
}
|
写了一些代码,现在我将构建并运行它。我输入的内容以粗体显示,屏幕上的内容以斜体显示。
j@j-desktop:~/badCode$ g++ 227.cpp
j@j-desktop:~/badCode$ ./a.out
段错误 (Segmentation fault)
糟糕,一个段错误。我将使用调试符号重新构建它,然后在调试器下运行它。
j@j-desktop:~/badCode$ g++ -g 227.cpp
j@j-desktop:~/badCode$ gdb ./a.out
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 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 "x86_64-linux-gnu".
For bug reporting instructions, please see:
<https://gnu.ac.cn/software/gdb/bugs/>...
Reading symbols from /home/j/badCode/a.out...done.
(gdb) run
Starting program: /home/j/badCode/a.out
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400824 in main () at 227.cpp:13
13 cout << "指针指向的值是 " << *p;
思考:好吧,段错误发生在这行。我在这里使用了一个指针 p。我最好检查一下那个指针的值。
(gdb) print p
$1 = (int *) 0x0
思考:啊哈!指针的值为零 - 这是一个空指针。尝试解引用它会导致段错误。让我们看看附近的code。
(gdb) list
int x = 7;
int *p = 0;
cout << "x = " << x;
cout << "指针指向的值是 " << *p;
}
思考:啊,我从来没有设置指针指向任何东西。这很容易修复。
(gdb) quit 调试会话正在活动中。
次级进程 1 [进程 6779] 将被终止。
仍然退出? (y 或 n)
修复代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
#include<iostream>
using namespace std;
int main()
{
int x = 7;
int *p = 0;
p = &x;
cout << "x = " << x;
cout << "The pointer points to the value " << *p;
}
|
现在构建并运行
j@j-desktop:~/badCode$ g++ 227.cpp
j@j-desktop:~/badCode$ ./a.out
x = 7指针指向的值是 7
所以我们得到了它。我使用的命令是
gdb ./a.out - 启动 gdb 并附加到我感兴趣的程序。这不会启动程序运行。
run - 启动程序运行
print p - 显示名为 p 的对象的值。
list - 显示执行已暂停的行,以及周围的代码行。
quit - 退出 gdb。
我建议你自己做类似的事情来练习一下。像这样追踪段错误非常容易。使用 gdb 仅需三十秒就可以确定确切的问题。我见过人们花费数小时试图手动完成它,盯着代码,到处打印变量,仅仅因为他们不想进入调试器。