gdb使用gdb與多線程gdb使用
gdb是非常強大的調(diào)試工具,在文本模式下使用。使用方法可以參考陳皓的兩篇文章 用GDB調(diào)試程序(一) 用GDB調(diào)試程序(二)
gdb常用命令在下表列出:
| 命令 | 描述 |
|---|
| backtrace(或bt) | 查看各級函數(shù)調(diào)用及參數(shù) |
| finish | 連續(xù)運行到當前函數(shù)返回為止,然后停下來等待命令 |
| frame(或f) | 幀編號 選擇棧幀 |
| info(或i) | locals 查看當前棧幀局部變量的值 |
| list(或l) | 列出源代碼,接著上次的位置往下列,每次列10行 |
| list 行號 | 列出從第幾行開始的源代碼 |
| list 函數(shù)名 | 列出某個函數(shù)的源代碼 |
| next(或n) | 執(zhí)行下一行語句 |
| PRint(或p) | 打印表達式的值,通過表達式可以修改變量的值或者調(diào)用函數(shù) |
| quit(或q) | 退出gdb調(diào)試環(huán)境 |
| set var | 修改變量的值 |
| start | 開始執(zhí)行程序,停在main函數(shù)第一行語句前面等待命令 |
| step(或s) | 執(zhí)行下一行語句,如果有函數(shù)調(diào)用則進入到函數(shù)中 |
gdb與多線程
在多線程編程時,當我們需要調(diào)試時,有時需要控制某些線程停在斷點,有些線程繼續(xù)執(zhí)行。有時需要控制線程的運行順序。有時需要中斷某個線程,切換到其他線程。這些都可以通過gdb實現(xiàn)。
先來看一下gdb調(diào)試多線程常用命令:
info threads:顯示可以調(diào)試的所有線程。gdb會為每個線程分配一個ID(和tid不同),編號一般從1開始。后面的ID是指這個ID。
thread ID:切換當前調(diào)試的線程為指定ID的線程。
break FileName.cpp:LinuNum thread all:所有線程都在文件FileName.cpp的第LineNum行有斷點。
thread apply ID1 ID2 IDN command:多個線程執(zhí)行g(shù)db命令command。
thread apply all command:所有線程都執(zhí)行command命令。
set scheduler-locking off|on|step:在調(diào)式某一個線程時,其他線程是否執(zhí)行。off,不鎖定任何線程,默認值。on,鎖定其他線程,只有當前線程執(zhí)行。step,在step(單步)時,只有被調(diào)試線程運行。
set non-stop on/off:當調(diào)式一個線程時,其他線程是否運行。
set pagination on/off:在使用backtrace時,在分頁時是否停止。
set target-async on/ff:同步和異步。同步,gdb在輸出提示符之前等待程序報告一些線程已經(jīng)終止的信息。而異步的則是直接返回。
來看一個例子: gdbTest.cpp。程序很簡單,只是讓兩個線程執(zhí)行函數(shù)ThreadFun,在函數(shù)中打印傳入的參數(shù)。
#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;}123456789101112131415161718192021222324252627282930313233343536123456789101112131415161718192021222324252627282930313233343536$ gdb gdbThreadTest//調(diào)試gdbThreadTest11加斷點
(gdb) break 7Breakpoint 1 at 0x400a19: file kangThread.cpp, line 7.(gdb) break 35Breakpoint 2 at 0x400b35: file kangThread.cpp, line 35.(gdb) info breakNum Type Disp Enb Address What1 breakpoint keep y 0x0000000000400a19 in ThreadFun(void*) at kangThread.cpp:72 breakpoint keep y 0x0000000000400b35 in main() at kangThread.cpp:351234567812345678開始運行
(gdb) rStarting 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_printersImportError: No module named 'libstdcxx'[New Thread 0x7ffff6fd5700 (LWP 2773)][Switching to Thread 0x7ffff6fd5700 (LWP 2773)]Breakpoint 1, ThreadFun (arg=0x602010) at kangThread.cpp:7warning: Source file is more recent than executable.7 int *value=static_cast<int*> (arg);12345678910111213141234567891011121314查看線程信息
(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:81123456123456可以看到ID為2的線程執(zhí)行到了斷點Breakpoint 1。可以看一下value的值
(gdb) n8 std::cout<<"This is thread"<<*value<<std::endl;(gdb) p *value$2 = 112341234切換到線程3,看一下線程3執(zhí)行到了哪里
(gdb) cContinuing.1[Switching to Thread 0x7ffff67d4700 (LWP 2774)]Breakpoint 1, ThreadFun (arg=0x602030) at kangThread.cpp:77 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:77 int *value=static_cast<int*> (arg);(gdb) n8 std::cout<<"This is thread"<<*value<<std::endl;(gdb) p *value$3 = 2123456789101112131415161718192021
123456789101112131415161718192021可以看出線程3的value為2。
還有其他許多命令和方法,要在實踐中慢慢熟悉。