1. Introduction to gdb
- The gdb tool is a debugging tool in the Linux environment. (This article is tested in the centos6.5 environment)
- The -g option must be added when compiling the source file.
- Start debugging: gdb binfile
- Exit method quit or ctrl+d.
Common commands for gdb debugging process:
list/l 行号:显示源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
r或run:运行程序。
s或step:进入函数调用
breaktrace(bt):查看各级函数调用及参数
info(i) locals:查看当前栈帧局部变量的值
info break :查看断点信息。
finish:执行到当前函数返回,然后挺下来等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
set var:修改变量的值
quit:退出gdb
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
continue(或c):从当前位置开始连续而非单步执行程序
run(或r):从开始连续而非单步执行程序
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
info(或i) breakpoints:参看当前设置了哪些断点
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X行号:跳至X行
p 变量:打印变量值
n 或 next:单条执行
2. Debugging multiple processes
By default, gdb will only debug the main process. If you want to debug multiple processes, you need to make some settings:
1. The show follow-fork-mode command and the show detach-on-fork
command are to view these two modes Settings:
The default follow-fork-mode is parent, detach-on-fork is on, and only the main process is debugged at this time.
2. The commands set follow-fork-mode and set detach-on-fork
can reset these two modes for multi-process debugging
. Follow-fork-mode has two options: [ parent ] and [ child ]
detach- There are two options for on-fork: [ on ] and [ off ]
Then there are the following four cases, each with different meanings:
1.parent on 只调试主进程(GDB默认)
2.child on 只调试子进程
3.parent off 同时调试两个进程,gdb跟主进程,子进程block在fork位置
4.child off 同时调试两个进程,gdb跟子进程,主进程block在fork位置
Set it as follows:
Test file:
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/wait.h>
5 #include<stdlib.h>
6 int main()
7 {
8 pid_t pid;
9 pid=fork();
10 if(pid<0)
11 {
12
13 perror("fork");
14 exit(1);
15
16 }
17 if(pid==0)
18 {//child
19 printf("I am Child,My id is:%d,My fathers id is:%d\n",getpid(),getppid());
20
21 }
22 if(pid>0)
23 {//father
24 printf("I am Father,My id is:%d\n",getpid());
25 wait(NULL);
26 }
27
28 return 0;
29 }
3. Next, set breakpoints in the parent and child processes respectively:
4. Run the program and query the running process:
For each debugged process, the operating system will assign him an inferior structure to describe the debugging of the process information, and assign an id to it, each process corresponds to an inferior, each different inferior has a different address space, and sometimes the inferior exists when the process has not been started.
5. Switch the debugged process:
inferior<infer number>
6. Other operations
Add debugging process
1.add-inferior [-copies n] [-exec executable]
Add one or more debug processes, n represents the number to be added, if not specified, one is added by default, and executable is the path of the debug file. If not specified, the program will be left blank. After adding, you can use the file command to re-specify the execution program. At this time, the process associated with the Inferior created is not started.
Delete the inferior numbered inferno. If the program is running, it cannot be deleted, it must be detached or killed first.
2.remove-inferior inferno
Copy n inferiors numbered inferno. If n is not specified, copy one. If inferno is not specified, the current process is copied by default.
3.clone-inferior [n][inferno]
Detach separates the inferior numbered inferno. Note that even if detached, the inferior still exists, waiting for the user to use the run command again to make it run.
4.detach-inferior inferno
Kill the Inferior numbered inferno. Note that even if it is removed, the Inferior still exists, waiting for the user to use the run command again to make it run.
5.kill-inferior inferno
6.set schedule-multiple on|off
When set to off: only the current Inferior will be executed
When set to on: All Inferiors in the execution state will be executed
7.scheduler-locking
Note that when scheduler-locking is on, even if scheduler-multiple is on, only the current thread of the current process will execute. The default is step. It can be viewed by show sheduler-locking,
8.set follow-exec-mode new|same
Set to new: When an exec occurs, control the child process on the inferior that executes the exec.
Set to the same: Create a new Inferior for the executing child process. The parent process's Inferior is still retained, and the program state of the currently retained Inferior is not executed.
9. set print inferior-events
It is used to set the status prompt information of Inferior, which can be set to on or off.
10.maint info program-spaces
Used to view how much address space is currently managed by GDB.
3. Debugging multithreading
gdb supports debugging multithreading by default. Like the main thread, the new thread block is where it was created.
Test file:
1 #include<stdio.h>
2 #include<pthread.h>
3
4 void *run1(void *arg)
5 {
6 printf("I am thread 1,My id is:%d\n",pthread_self());
7 }
8 void * run2(void *arg)
9 {
10 printf("I am thread2 ,My id is:%d\n",pthread_self());
11 }
12 int main()
13 {
14 pthread_t t1,t2;
15 pthread_create(&t1,NULL,run1,NULL);
16 pthread_create(&t2,NULL,run2,NULL);
17 pthread_join(t1,NULL);
18 pthread_join(t2,NULL);
19 return 0;
20 }
21
Two threads are created here, so there are three threads in total. Here are two breakpoints inside the two thread functions respectively.
1. Common commands for debugging multithreading
1.info threads
When debugging multiple threads, gdb will assign a thread id to each thread, generally starting from 1, where the thread id is different from t1. We can look at the thread situation, since our first breakpoint is in thread run1, thread 2 is running.
2.thread ID
Switch the debugging thread, the ID is the thread number.
3.show scheduler-locking
set scheduler-locking on|off|step
Check the thread lock status and set the thread lock status. When set to on, lock the rest of the threads, and only the current thread will run. Set to off to not lock any threads, default value. When set to step, only the thread being debugged will run.
4.thread apply id1 id2 id3 commond
thread apply all commond
The first is to let the specified threads 1, 2, and 3 execute the commond command, and the second is that all threads execute the commond command.
5.break FileName.cpp:LinuNum thread all:
All threads have a breakpoint at line LineNum of the file FileName.cpp.
6.set target-async on/ff
Synchronous and asynchronous. Synchronous, gdb waits for the program to report that some thread has terminated before outputting the prompt. Asynchronous, on the other hand, returns directly.