gdb在命令的首字母唯一时是可以缩写的。
b/break 函数名
:给函数设置断点。
c/continue
:继续执行。
b/break 文件名.c:行号
:在指定文件的指定行设置断点。
next
:单步执行程序,如果是函数则将函数整体执行,不会进入。
回车键
:执行上次的命令。
file 可执行文件名
:调试指定的文件。
s/step
:单步执行程序,如果是函数则会进入。
l/list
:显示当前行下面的10行代码。
p/print 变量名
:查看变量的值。也可以查看函数的值(地址)。
i/info b/break
:查询断点信息。
d/delete
:删除所有的断点。
d/delete 断点序号
:删除第几个断点。
attach pid
:调试运行中的进程id为pid的程序。
#include
int add(int num1, int num2){
return num1 + num2;
}
int main(){
int a = 5;
int b = 8;
int ret = add(a,b);
printf("%d + %d = %d\n", a, b, ret);
return 0;
}
调试必须在编译时加入 -g
,然后再输入file 可执行文件名
,编译时如果没有指定文件名,默认是a.out
。
先在add
函数处添加了断点,然后直接运行程序。
执行n
指令,继续走一步,来到第五行。
再次执行n
指令,也就是ret
赋值完毕,来到第11行。
按下回车
,执行上一次的指令,也就是n
,执行printf
语句打印出信息,显示了下一行的语句:return 0;
#include
#include
void printHello(int times){
printf("Hello -- %d\n", times);
}
int main(){
for(int i=0;i<10000;i++){
printHello(i);
sleep(3); // 睡眠3秒
}
return 0;
}
for循环如果报错,要加一个-std=c99
。
-o
可以指定可执行程序的名称,这里我将demo2.c
的可执行文件名称指定为demo2
。
测试一下:
如果打印操作不是通过
printHello
函数,并且printf中没有\n
,那么是没有打印结果的。
需要加上\n
,或者是fflush(stdout);
刷新一下缓冲区。
这是因为printf的输出结果被放在缓冲区,如果没有换行符或者刷新缓冲区,不会有输出。
这次我们要调试运行中的程序,所以要获取该程序的进程id
。
ps -ef | grep 进程名
先运行程序,然后从另一个终端中搜索该程序的进程号:
这里的10237
就是PID(process identity)
attach 10237
:调试PID为10237的程序。b demo2.c:10
在demo2.c
的第10行打一个断点,同时左边终端到Hello --58
就停住了,没有再输出信息。sleep(3)
,提示我们下一次要执行的是:9 for(int i=0;i<10000;i++)\{
也就是第9行的for循环体。
果然进入了第5行的函数体中。