我们这里仍旧将gdb的基本操作在这里罗列一下:
•list(l)行号:显示源代码。一次显示10行
•list(l)函数名:列出某个函数的源代码
•r或run:运行程序
•s或step:进入函数调用
•breaktrace(bt):查看函数调用栈
•info(i) locals:查看当前栈帧局部变量的值
•info break :查看断点信息
•finish:执行到当前函数返回,然后停下来等待命令
•print(p):打印表达式的值
•set var:修改变量的值
•quit(q):退出gdb
•break(b) 行号:在某一行设置断点
•break 函数名:在某个函数开头设置断点
•continue(c):从当前位置开始连续而非单步执行程序
•run(r):从开始连续而非单步执行程序
•delete(d)break:删除所有断点
•delete(d)break n:删除序号为n的断点
•disable break:禁用断点
•enable break:启用断点
•info(i) break:参看当前设置了断点
•next(n):单条执行
在Linux下默认是可以调试多线程的。接下来,我们先写简单的测试用例。
#include <stdio.h>
#include <pthread.h>
void* thread1(void* arg)
{
printf("i am %s!\n",(char*)arg);
return (void*)0;
}
void* thread2(void* arg)
{
printf("i am %s!\n",(char*)arg);
return (void*)0;
}
void* thread3(void* arg)
{
printf("i am %s!\n",(char*)arg);
return (void*)0;
}
int main()
{
pthread_t tid1, tid2, tid3;
pthread_create(&tid1, NULL, thread1, (void*)"thread1");
pthread_create(&tid2, NULL, thread2, (void*)"thread2");
pthread_create(&tid3, NULL, thread3, (void*)"thread3");
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
return 0;
}
这里创建了三个线程,所以加上主线程,总共四个线程。在gdb下,默认是可以进行多线程的调试的。这与进程不同,所以不需要设置任何选项。我们这时候开始对测试代码进行gdb调试。首先我们先进入gdb调试模式。然后list查看源码。这里不再赘述。我们这里先在第30行打断点。这个时候刚刚创建完线程一,此时进程中有两个线程(主线程与线程一)。
打完断点之后,我们可以用指令run(r)让进程跑起来,此时到达断点。已执行完创建第一个线程的代码。这个时候我们用指令info threads
来查看当前可调试的线程。发现分别有两个编号为1与2的线程。
此时*
代表正在调试的线程。编号为gdb编号,与我们的线程ID并没有关系,这个编号是为了方便与我们调试的时候切换想要调试的线程。这时候我们再对31行进行打断点。同样用info threads
来查看一下。
这个时候我们发现,可调式的线程变成了一号与三号,这是为什么?原因是上面线程一已经跑完了,所以在进程内部已经没有了线程一。所以只剩下两个线程,主线程与线程二。线程二的编号为3。我们假如要切换调试线程,可以用thread
加线程编号,来进行切换。
切换完毕后,我们再用info threads
进行查看,这个时候*
在我们切换的线程编号旁边,也就是说,现在调试的是编号为三的线程。
在我们可以切换要调试的线程的时候,我们就可以对任意线程进行调试。
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!