gdb多线程篇

能力介绍

  • gdb能调试多线程程序,可以同时调试多个进程.

  • 支持远程调试,即执行在另一个系统上的程序.另一个系统可以是不同平台.

inferior

  • 用这么一个对象表示一个调试程序.不管有没有执行,都会记录.
  • 调试某个程序,调试多个程序就有多个inferior.

  • 默认创建一个,被调试程序不管有没有执行,即程序执行前存在,程序终止后也存在。

  • 可以理解为一个调试会话。一个程序一个会话。或者说一个进程一个会话,不过进程执行前和执行后都存在,所以用进程也不是很准确。

查看调试的程序

查看调试的程序info inferiors

chen@chen:~/cppfile/test$ g++ test.cpp -g
chen@chen:~/cppfile/test$ gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) info inferiors
 Num  Description       Executable
* 1    <null>            /home/chen/cppfile/test/a.out
(gdb) break main
Breakpoint 1 at 0x4004d6: file test.cpp, line 2.
(gdb) r
Starting program: /home/chen/cppfile/test/a.out

Breakpoint 1, main () at test.cpp:2
2       }
(gdb) info inferiors
 Num  Description       Executable
* 1    process 9371      /home/chen/cppfile/test/a.out

  • 可以看到到调试的程序,在启动之前也有,只是没有执行信息.
  • 分析: *表示当前进程和线程。 1表示当前调试程序会话编号为1description的值表示这个进程的进程号是9371,可以通过/proc/pid/查看信息。executable表示路径。
  • 有的可能有五列: 当前执行,进程描述,远程还是本地,可执行文件.

查看当前的会话

  • inferror

多线程

多线程的本质

  • 就是多个进程共享了一些数据(地址空间,堆,text,bss等)的进程组合。

查看线程info threads

chen@chen:~/cppfile/test$ gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) b main
Breakpoint 1 at 0x400625: file test.cpp, line 9.
(gdb) r
Starting program: /home/chen/cppfile/test/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at test.cpp:9
9           pthread_create(&tid,nullptr,run,nullptr);
(gdb) n
[New Thread 0x7ffff77f2700 (LWP 9412)]
10          pthread_join(tid,nullptr);
(gdb) printf "%p\n",tid
0x7ffff77f2700
(gdb) info threads
 Id   Target Id                                Frame
* 1    Thread 0x7ffff7fed740 (LWP 9408) "a.out" main () at test.cpp:10
 2    Thread 0x7ffff77f2700 (LWP 9412) "a.out" 0x0000000000400612 in run () at test.cpp:4

  • *表示当前调试的线程.
  • ID表示线程在调试器中的内部编号,这里是1
  • Target ID表示当前的线程信息.lwp:light weight process轻量级线程就是进程嘛.9412就是线程号./proc/9408/task/9412就是全局进程号,这里是线程就是线程号好了。中间那个地址就是tid的值,即pthread结构体的首地址。

线程切换

(gdb) list
5           return nullptr;
6       }
7       int main() {
8           pthread_t tid;
9           pthread_create(&tid,nullptr,run,nullptr);
10          pthread_join(tid,nullptr);
11      }
(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff77f2700 (LWP 9412))]
#0  0x0000000000400612 in run () at test.cpp:4
4           while(!stop);
(gdb) list
1       #include<pthread.h>
2       int stop = false;
3       void* run(void*) {
4           while(!stop);
5           return nullptr;
6       }
7       int main() {
8           pthread_t tid;
9           pthread_create(&tid,nullptr,run,nullptr);
10          pthread_join(tid,nullptr);

  • thread id表示切换到目标线程。
  • 分别用list查看代码,可以看到显示的不一样。

多进程调试

编号差异

chen@chen:~/cppfile/test$ gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) clone-inferior
[New inferior 2 (process 0)]
Added inferior 2.
(gdb) info inferiors
 Num  Description       Executable
* 1    <null>            /home/chen/cppfile/test/a.out
 2    <null>            /home/chen/cppfile/test/a.out
(gdb) break main
Breakpoint 1 at 0x400625: main. (2 locations)
(gdb) r
Starting program: /home/chen/cppfile/test/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at test.cpp:9
9           pthread_create(&tid,nullptr,run,nullptr);
(gdb) n
[New Thread 0x7ffff77f2700 (LWP 9422)]
10          pthread_join(tid,nullptr);
(gdb) info inferiors
 Num  Description       Executable
* 1    process 9418      /home/chen/cppfile/test/a.out
 2    <null>            /home/chen/cppfile/test/a.out
(gdb) inferior 2
[Switching to inferior 2 [<null>] (/home/chen/cppfile/test/a.out)]
(gdb) info inferiors
 Num  Description       Executable
 1    process 9418      /home/chen/cppfile/test/a.out
* 2    <null>            /home/chen/cppfile/test/a.out
(gdb) break main
Note: breakpoint 1 also set at pc 0x400625.
Note: breakpoint 1 also set at pc 0x400625.
Breakpoint 2 at 0x400625: main. (2 locations)
(gdb) r
Starting program: /home/chen/cppfile/test/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Thread 2.1 "a.out" hit Breakpoint 1, main () at test.cpp:9
9           pthread_create(&tid,nullptr,run,nullptr);
(gdb) n
[New Thread 0x7ffff77f2700 (LWP 9424)]
10          pthread_join(tid,nullptr);
(gdb) info threads
 Id   Target Id                                Frame
 1.1  Thread 0x7ffff7fed740 (LWP 9418) "a.out" main () at test.cpp:10
 1.2  Thread 0x7ffff77f2700 (LWP 9422) "a.out" 0x0000000000400612 in run () at test.cpp:4
* 2.1  Thread 0x7ffff7fed740 (LWP 9423) "a.out" main () at test.cpp:10
 2.2  Thread 0x7ffff77f2700 (LWP 9424) "a.out" 0x0000000000400612 in run () at test.cpp:4

  • 首先是使用指令clone-inferior 创建了一个一模一样的环境。
  • 然后分别设置断点。
  • 再查看线程编号。
  • 可以看到ID出现了轻微的变化。1.1了,前面的就是inferior的编号,后面就是线程的编号。
  • 同样的*表示当前正在调试的线程。