在Windows下调试程序我们直接打断点F10,F11等键加上监事窗口的调试程序就很方便了,但是在Linux下并没有集成的开发调试环境这时就要用到GDB
GDB常用调试命令
l ist/l ⾏行号:显⽰示binFile源代码,接着上次的位置往下列,每次列10⾏行。
list/l 函数名:列出某个函数的源代码。
r或run:运⾏行程序。
s或step:进⼊入函数调⽤用
breaktrace(或bt):查看各级函数调⽤用及参数
info(i) locals:查看当前栈帧局部变量的值
info break :查看断点信息。
finish:执⾏行到当前函数返回,然后挺下来等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或者调⽤用函数
set var:修改变量的值
quit:退出gdb
break(b) ⾏行号:在某⼀一⾏行设置断点
break 函数名:在某个函数开头设置断点
continue(或c):从当前位置开始连续⽽而⾮非单步执⾏行程序
run(或r):从开始连续⽽而⾮非单步执⾏行程序
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁⽤用断点
enable breakpoints:启⽤用断点
info(或i) breakpoints:参看当前设置了哪些断点
display 变量名:跟踪查看⼀一个变量,每次停下来都显⽰示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X⾏行号:跳⾄至X⾏
n 或 next:单条执⾏行。
p 变量:打印变量值。
对于多进程程序
set follow-fork-mode child //GDB调试子进程
set follow-fork-mode parent //GDB调试父进程
gdb 默认调试主进程
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void child()
{
int i=0;
printf("child pid = %d,ppid == %d\n",getpid(),getppid());
for(i;i<10;i++){
sleep(1);
printf("child: %d\n",i);
}
}
void father()
{
int i=20;
printf("father pid = %d,ppid = %d\n",getpid(),getppid());
for(i;i>0;i--){
sleep(1);
printf("father:%d\n",i);
}
}
int main()
{
pid_t id = fork();
if (0 == id){
child();
}else{
sleep(1);
father();
}
}
正常这段代码执行的结果是这样的
使用set follow-fork-mode child在GDB中调试的结果是这样
调试父进程
GDB中还有set detach-on-fork on/off这个命令和set follow-fork-mode parent/child 组合使用
follow-fork-mode detach-on-fork 说明
parent on GDB默认的调试方式;只调试主进程
child on 只调试子进程
parent off 同时调试两个进程,gdb跟主进程,子进程block在fork位置
child off 同时调试两个进程,gdb跟子进程,主进程block在fork位置
调试线程
查询线程 info threads
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void* thread1(void* arg)
{
int i=0;
for (i;i<10;i++){
printf("%d\n",i);
sleep(1);
}
}
void* thread2(void* arg)
{
int i=10;
for (i;i>0;i--){
sleep(1);
printf("%d\n",i);
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
pthread_create(&tid1,NULL,thread1,NULL);
pthread_create(&tid2,NULL,thread2,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
提示创建新进程
线程切换thread 加线程编号调试该线程