liuchang@DESKTOP-LIUCHANG:~/codetest$ gdb main GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type"show copying" and "show warranty"for details. This GDB was configured as "x86_64-linux-gnu". Type"show configuration"for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type"help". Type"apropos word" to search for commands related to "word"... Reading symbols from main...done. (gdb) l 101 102#include <iostream> 103using std::cout; 104using std::endl; 105 106 int func(int n){ 107 int sum = 0; 108for(int i=1;i<=n;i++){ 109 sum+=i; 110 } (gdb) l 111return sum; 112 } 113 114 int main(){ 115 long result =0; 116for(int i=1;i<=50;i++){ 117 result+=i; 118 } 119 cout<<"result[1-50] =" <<result<<endl; 120 cout<<"result[1-60] =" <<func(60)<<endl; (gdb) l 121return0; 122 }(gdb) Line number 123 out of range; main.cpp has 122 lines. (gdb) break115 Breakpoint 1 at 0x991: file main.cpp, line 115. (gdb) break func Breakpoint 2 at 0x961: file main.cpp, line 107. (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000000991 in main() at main.cpp:115 2 breakpoint keep y 0x0000000000000961 in func(int) at main.cpp:107
(gdb) r Starting program: /home/liuchang/codetest/main
Breakpoint 1, main () at main.cpp:115 115 long result =0; (gdb) n 116for(int i=1;i<=50;i++){ (gdb) n 117 result+=i; (gdb) n 116for(int i=1;i<=50;i++){ (gdb) n 117 result+=i; (gdb) c Continuing. result[1-50] =1275
Breakpoint 2, func (n=60) at main.cpp:107 107 int sum = 0; (gdb) n 108for(int i=1;i<=n;i++){ (gdb) p i $1 = 0 (gdb) n 109 sum+=i; (gdb) n 108for(int i=1;i<=n;i++){ (gdb) p i $2 = 1 (gdb) n 109 sum+=i; (gdb) n 108for(int i=1;i<=n;i++){ (gdb) p i $3 = 2 (gdb)
bt 查看堆栈
finish退出函数
q退出gdb
1 2 3 4 5 6 7 8 9 10 11 12 13
(gdb) bt #0 func (n=60) at main.cpp:109 #1 0x0000000008000a0f in main () at main.cpp:120 (gdb) finish Run till exit from #0 func (n=60) at main.cpp:109 0x0000000008000a0f in main () at main.cpp:120 120 cout<<"result[1-60] =" <<func(60)<<endl; Value returned is $5 = 1830 (gdb) c Continuing. result[1-60] =1830 [Inferior1 (process26871) exitednormally] (gdb) q
b break的缩写,加断点。 info break [n] 查看断点 l list 缩写查看源码 c continue缩写,恢复运行。 step命令可以缩写为s, 命令被执行一次代码被向下执行一行,如果这一行是一个函数调用,那么程序会进入到函数体内部。 n next缩写,单步跟踪程序。next命令和step命令功能是相似的,只是在使用next调试程序的时候不会进入到函数体内部。 p print缩写,可以查看变量值。 p file::variable 某文件中的变量 p function::variable 全局变量 p *array@len 查看数组内容。 p/x 十六进制格式显示变量。其他格式的变量也有。 display i 变量自动显示。 whatis para 查看para的类型 finish 运行程序,直到当前程序函数完成,并打印函数返回时的堆栈地址和返回值及参数值等信息。 until 或 u 运行程序直到结束循环结构。 info agrs 查看函数名和参数值 info locals 打印当前函数中所有局部变量及其值 info line查看源代码内存地址 disassemble func 可以查看函数func的汇编代码。 set listsize n 设置一次显示源代码的行数。 q quit的缩写,退出gdb。
set args 可指定运行时参数。如:set args 10 20 30 40 50 show args 命令可以查看设置好的运行参数。 path dir 可设定程序的运行路径。 show paths cd / pwd run > outfile重定向输出
tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb
调试已经运行的程序 两种方法: 1、在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdb program PID格式挂接正在运行的程序。 2、先用gdb program关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。
if test $# -ne 1; then echo"Usage: `basename $0 .sh` <process-id>"1>&2 exit1 fi
if test ! -r /proc/$1; then echo"Process $1 not found."1>&2 exit1 fi
# GDB doesn't allow "thread apply all bt" when the process isn't # threaded; need to peek at the process to determine if that or the # simpler "bt" should be used.
backtrace="bt" if test -d /proc/$1/task ; then # Newer kernel; has a task/ directory. if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt12>/dev/null ; then backtrace="thread apply all bt" fi elif test -f /proc/$1/maps ; then # Older kernel; go by it loading libpthread. if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then backtrace="thread apply all bt" fi fi
GDB=${GDB:-/usr/bin/gdb}
if$GDB-nx--quiet--batch--readnever > /dev/null 2>&1; then readnever=--readnever else readnever= fi
# Run GDB, strip out unwanted noise. $GDB--quiet$readnever-nx /proc/$1/exe $1 <<EOF 2>&1 | set width 0 set height 0 set pagination no $backtrace EOF /bin/sed -n \ -e's/^\((gdb) \)*//' \ -e'/^#/p' \ -e'/^Thread/p'
(gdb) b 12 Breakpoint 1 at 0xaf6: file main.cpp, line 12. (gdb) b 20 Breakpoint 2 at 0xb61: file main.cpp, line 20. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000000af6 in thread_entry_funcA(void*) at main.cpp:12 2 breakpoint keep y 0x0000000000000b61 in thread_entry_funcB(void*) at main.cpp:20 (gdb) r Starting program: /home/liuchang/codetest/main [Threaddebuggingusinglibthread_dbenabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [NewThread0x7ffff6e83700 (LWP835)] [NewThread0x7ffff6682700 (LWP836)] [SwitchingtoThread0x7ffff6e83700 (LWP835)]
Thread 2"main" hit Breakpoint 1, thread_entry_funcA (arg=0x0) at main.cpp:12 12 cout<<"[thread_entry_funcA]: "<<i<<endl; (gdb) info threads Id Target Id Frame 1 Thread 0x7ffff7fe8740 (LWP 831) "main" clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:78 * 2 Thread 0x7ffff6e83700 (LWP 835) "main" thread_entry_funcA (arg=0x0) at main.cpp:12 3 Thread 0x7ffff6682700 (LWP 836) "main" thread_entry_funcB (arg=0x0) at main.cpp:20 (gdb) bt #0 thread_entry_funcA (arg=0x0) at main.cpp:12 #1 0x00007ffff7bbb6db in start_thread (arg=0x7ffff6e83700) at pthread_create.c:463 #2 0x00007ffff755b61f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 (gdb) f 0 #0 thread_entry_funcA (arg=0x0) at main.cpp:12 12 cout<<"[thread_entry_funcA]: "<<i<<endl; (gdb) n #想要执行线程A,但是发现线程切换到了线程B [SwitchingtoThread0x7ffff6682700 (LWP836)]
Thread 3"main" hit Breakpoint 2, thread_entry_funcB (arg=0x0) at main.cpp:20 20 cout<<"[thread_entry_funcB]: "<<i<<endl;