转自:http://blog.csdn.net/chn89/article/details/7098846
GDB是*nix下常用的调试工具,可以提供及其复杂的调试功能,功能十分强大。这里展示一下GDB调试多线程的常规方法。
常用命令:
info threads :显示当前可以调试的所有线程。
thread IDx : IDx请用上述命令中的线程ID替换,该命令用于切换被调试的线程,请注意GDB只能调试一个执行序列,也就一个传统意义上的进程
break file.c:20 thread all:在file.c中的第20行,为所有经过这里的线程设置断点
set scheduler-locking off|on|step:线程之间是并行执行的,step之类的命令会对所有线程生效。该命令就是提供了一种只对单一线程生效的解决方式。选项off表示不锁定任何进程,也就是默认情况。on表示命令只对当前线程生效。step表示在单步的时候,除了next过一个函数的情况以外,只对当前线程执行。
使用举例:
应用1,下面代码会产生coredump,我们调试之。
- #include <stdio.h>
- #include <pthread.h>
- int a(void){
- sleep(2);
- return 0;
- }
- int b(){
- a();
- return 0;
- }
- int c(){
- b();
- return 0;
- }
- void *myThread1(void)
- {
- int i=9;
- while(i>0)
- {
- printf("Our 1st pthread,created by chn89.\n");
- sleep(2);
- i--;
- c();
- }
- pthread_exit(0);
- }
- void *myThread2(void)
- {
- int i=5;
- while(i>0)
- {
- printf("Our 2st pthread,created by chn89.\n");
- sleep(2);
- i--;
- }
- pthread_exit(0);
- }
- int main()
- {
- int ret=0;
- pthread_t thread_id1,thread_id2;
- ret = pthread_create(&thread_id1, NULL, (void*)myThread1, NULL); //这里笔误,应为thread_id1 就是调试这里的错误
- if (ret)
- {
- printf("Create pthread error!\n");
- return 1;
- }
- ret = pthread_create(&thread_id2, NULL, (void*)myThread2, NULL);
- if (ret)
- {
- printf("Create pthread error!\n");
- return 1;
- }
- pthread_join(thread_id1, NULL);
- pthread_join(thread_id2, NULL);
- return 0;
- }
执行会提示segment错误,并提示产生coredump。但是却没有产生。需要执行ulimit -c unlimited。再执行一次,才真正的产生了coredump文件。
执行gdb a.out corefile 并执行bt查看执行backtrace,显示第49行执行错误。也就是初步怀疑线程1运行有问题。
执行
gdb a.out
(gdb) b 49
(gdb) thread 2 //主线程是1
(gdb) c
之后发现线程2工作正常,同理对线程2,也正常。按理pthread_join()是库函数不应该有问题,仔细检查发现,XX的笔误。这里提供了单独调试线程的方法,各位可以一试。
应用2,代码是修正笔误的上述代码,这里假设上述代码已经处于运行状态,但是跑飞了,需要确定各线程执行位置。
- gdb a.out pid -- pid是运行的进程号
- (gdb) thread 2
- (gdb) bt
- #0 0x00855416 in __kernel_vsyscall ()
- #1 0x00bf1086 in nanosleep () from /lib/libc.so.6
- #2 0x00bf0ea4 in sleep () from /lib/libc.so.6
- #3 0x08048516 in a () at pthread_gdb.c:5
- #4 0x08048528 in b () at pthread_gdb.c:10
- #5 0x0804853a in c () at pthread_gdb.c:15
- #6 0x08048571 in myThread1 () at pthread_gdb.c:26
- #7 0x00cede99 in start_thread () from /lib/libpthread.so.0
- #8 0x00c2cd2e in clone () from /lib/libc.so.6
- 可以看出线程1的backtrace,正在执行函数a中的sleep呢。