转载地址: http://blog.csdn.net/kangroger/article/details/47986197
gdb与多线程
在多线程编程时,当我们需要调试时,有时需要控制某些线程停在断点,有些线程继续执行。有时需要控制线程的运行顺序。有时需要中断某个线程,切换到其他线程。这些都可以通过gdb实现。
先来看一下gdb调试多线程常用命令:
-
info threads:显示可以调试的所有线程。gdb会为每个线程分配一个ID(和tid不同),编号一般从1开始。后面的ID是指这个ID。
-
thread ID:切换当前调试的线程为指定ID的线程。
-
break FileName.cpp:LinuNum thread all:所有线程都在文件FileName.cpp的第LineNum行有断点。
-
thread apply ID1 ID2 IDN command:多个线程执行gdb命令command。
-
thread apply all command:所有线程都执行command命令。
-
set scheduler-locking off|on|step:在调式某一个线程时,其他线程是否执行。off,不锁定任何线程,默认值。on,锁定其他线程,只有当前线程执行。step,在step(单步)时,只有被调试线程运行。
-
set non-stop on/off:当调式一个线程时,其他线程是否运行。
-
set pagination on/off:在使用backtrace时,在分页时是否停止。
-
set target-async on/ff:同步和异步。同步,gdb在输出提示符之前等待程序报告一些线程已经终止的信息。而异步的则是直接返回。
来看一个例子:
gdbTest.cpp。程序很简单,只是让两个线程执行函数ThreadFun,在函数中打印传入的参数。
#include <iostream> #include <pthread.h> void* ThreadFun(void* arg) { int *value=static_cast<int*> (arg); std::cout<<"This is thread"<<*value<<std::endl; pthread_exit(0); } int main() { int ret=0; pthread_t thread_id1,thread_id2; int* v1=new int(1); int* v2=new int(2); ret = pthread_create(&thread_id1, NULL, ThreadFun, static_cast<void*>(v1)); if (ret) { std::cout<<"Create pthread error!"<<std::endl; return 1; } ret = pthread_create(&thread_id2, NULL, ThreadFun, static_cast<void*>(v2)); if (ret) { std::cout<<"Create pthread error!"<<std::endl; return 1; } pthread_join(thread_id1, NULL); pthread_join(thread_id2, NULL); return 0; }[root@SpinfoServer src]# gdb -tui ./gdbthreadtest //调试程序
设置断点:
(gdb) break 7 Breakpoint 1 at 0x400a19: file kangThread.cpp, line 7. (gdb) break 35 Breakpoint 2 at 0x400b35: file kangThread.cpp, line 35. (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000400a19 in ThreadFun(void*) at kangThread.cpp:7 2 breakpoint keep y 0x0000000000400b35 in main() at kangThread.cpp:35开始运行:
(gdb) r Starting program: /home/kang/src/mulThread/kangThread [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Traceback (most recent call last): File "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py", line 63, in <module> from libstdcxx.v6.printers import register_libstdcxx_printers ImportError: No module named 'libstdcxx' [New Thread 0x7ffff6fd5700 (LWP 2773)] [Switching to Thread 0x7ffff6fd5700 (LWP 2773)] Breakpoint 1, ThreadFun (arg=0x602010) at kangThread.cpp:7 warning: Source file is more recent than executable. 7 int *value=static_cast<int*> (arg);查看线程信息:
(gdb) info thread [New Thread 0x7ffff67d4700 (LWP 2774)] Id Target Id Frame 3 Thread 0x7ffff67d4700 (LWP 2774) "kangThread" clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:81 * 2 Thread 0x7ffff6fd5700 (LWP 2773) "kangThread" ThreadFun (arg=0x602010) at kangThread.cpp:7 1 Thread 0x7ffff7fda780 (LWP 2769) "kangThread" clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:81可以看到ID为2的线程执行到了断点Breakpoint 1。可以看一下value的值
(gdb) n 8 std::cout<<"This is thread"<<*value<<std::endl; (gdb) p *value $2 = 1切换到线程3:
(gdb) c Continuing. 1 [Switching to Thread 0x7ffff67d4700 (LWP 2774)] Breakpoint 1, ThreadFun (arg=0x602030) at kangThread.cpp:7 7 int *value=static_cast<int*> (arg); (gdb) info thread Id Target Id Frame * 3 Thread 0x7ffff67d4700 (LWP 2774) "kangThread" ThreadFun (arg=0x602030) at kangThread.cpp:7 2 Thread 0x7ffff6fd5700 (LWP 2773) "kangThread" __GI__dl_debug_state () at dl-debug.c:74 1 Thread 0x7ffff7fda780 (LWP 2769) "kangThread" 0x00007ffff7bc566b in pthread_join (threadid=140737337186048, thread_return=0x0) at pthread_join.c:92 (gdb) thread 3 [Switching to thread 3 (Thread 0x7ffff67d4700 (LWP 2774))] #0 ThreadFun (arg=0x602030) at kangThread.cpp:7 7 int *value=static_cast<int*> (arg); (gdb) n 8 std::cout<<"This is thread"<<*value<<std::endl; (gdb) p *value $3 = 2
可以看出线程3的value为2。
还有其他许多命令和方法,要在实践中慢慢熟悉。