网络上已经有很多gdb调试的文章了,为什么我还要写这篇文章呢,因为本文是写给gdb新手的,目的就是通过一个简单的例子来让新手很快上手。一旦上手入门了,其他的问题就可以自己去搜索搞定了。右边是gdb的Logo,为啥是条吹泡泡的小鱼呢?我也不懂啊。
#include <stdio.h>
2
void print_str(char* str){
printf("%s", str);
str[] = 'a';
printf("\n");
}
int main(){
char* str = "hello, world!"; print_str(str); return ;
}
gcc -g main.c -o main -Wall -O0
-g Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this debugging
information. 简单来说就是在生成的可执行程序中加上gdb调试用的信息,如代码的行号和机器码的对应关系,符号表等信息。没有这类信息,在gdb里是看不到程序的函数名和变量名的
-o file
Write output to file. 定义输出文件的名称
-Wall Turns on all optional warnings which are desirable for normal code. 打开所有的警告信息,可以帮助我们通过warning来发现bug
-O 控制优化的级别, -O0Do not optimize. This is the default. 代码经过优化后,可能出现机器码和源代码对不上的问题。
./main
Segmentation fault
程序出错啦,段错误,一般是访问越界或者是尝试修改只读属性的内存造成的。
此时,可以用两种方法来调试这个程序:
语法:gdb /path/program-name
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.-.el5)
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/csd/main...done.
(gdb)
此时进入了gdb的命令行,跟shell一样,提供自动补全等功能,所以如果不计得命令的全称时,可以按tab键补全。
此时用 l [list] 命令(l是命令的简写,方括号中是命令的全称)来显示源码,也可以 l linenumber 来显示指定行号处的源码,也可以用 l 命名空间::类名::函数名来显示指定的函数,可以按tab键补全哦
(gdb) l
#include <stdio.h> void print_str(char* str){
printf("%s", str);
str[] = 'a';
printf("\n");
}
int main(){
char* str = "hello, world!";
可以看到默认显示10行源代码,想要继续看10行之后的代码,可以继续用 l 命令,也可以直接按回车,会重复上次的命令。
。如果觉得显示的源代码行数不够多,可以用 set listsize number 来设置一次显示源代码的行数。设置完成后,可以用 show listsize 命令来查看设置之后 listsize 变量的值。
此时我们想在程序开始处加断点,使用 b [break] linenumber 命令在指定行处设置断点,也可以用 b 命名空间::类名::函数名来在指定的函数处设置断点
(gdb) b 9
Breakpoint 1 at 0x400522: file main.c, line 9.
(gdb) r
Starting program: /home/csd/main Breakpoint 1, main () at main.c:9
9 char* str = "hello, world!";
(gdb)
此时程序停止在了断点1处,如果我们想看str的值怎么办?用 p [print] 变量名 来查看变量的值
(gdb) p str
$ = 0x0
(gdb)
此时还没有执行给str赋值的操作。然后用 n [next] 来单步执行下一条语句,然后再打印str的值,可以看到str已经被准确初始化了。
(gdb) n
print_str(str);
(gdb) p str
$ = 0x40063b "hello, world!"
(gdb)
此时程序将要执行第11行,print_str函数,我们想单步进入这个函数,可以用 step 命令
(gdb) step
print_str (str=0x40063b "hello, world!") at main.c:
printf("%s", str);
(gdb)
可以看到程序将要执行main.c文件中的print_str函数处的第4行,同时gdb会显示函数参数的地址和值。然后我们用 n 来单步执行
(gdb) n
str[] = 'a';
(gdb) n Program received signal SIGSEGV, Segmentation fault.
0x000000000040050b in print_str (str=0x40063b "hello, world!") at main.c:
str[] = 'a';
(gdb)
单步执行到第5行时出错了,程序收到操作系统发出的段错误信号。此时我们恍然大悟,尝试修改字符串常量的值,所以出错了。
运行程序:
./csd/main
Segmentation fault (core dumped)
此时发生段错误时,在当前工作目录下,产生了core dump文件:core.32624
加载core dump文件调试的语法: gdb /path/program-name /path/core-file
执行命令:
gdb ./main core.32624
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5)
Copyright (C) 2009 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
./main: No such file or directory.
[New Thread 32624]
Core was generated by `./csd/main'.
Program terminated with signal 11, Segmentation fault.
#0 0x000000000040050b in ?? ()
(gdb)
细心的读者会发现,gdb的显示的信息中,提示没有找到./main这个文件或目录。这是由于我切换目录(/home/csd/) 到了上一级目录(/home),导致gdb找不到main程序的源文件。此时可以设置 dir [directories] 变量来设置源代码的查找目录
(gdb) dir ./csd/
Source directories searched: /home/shengdong.csd/./csd:$cdir:$cwd
(gdb)
(gdb) bt
# 0x000000000040050b in print_str (str=0x40063b "hello, world!") at main.c:
# 0x0000000000400533 in main () at main.c:
(gdb)
可以看到程序时在main.c函数的第7行出问题的,然后用 l 7 来显示第7行上下的源代码,发现问题的所在。
另外,还有一种调试方法:
陈浩写的很详细,总共七部分。四和七在页面上没有链接,可以google一下,就能找到了。网上也有人整理成了pdf的文档,方便阅读。
如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!