1. 程式人生 > >gdb 除錯多程序、多執行緒的小栗子

gdb 除錯多程序、多執行緒的小栗子

gdb除錯中多執行緒是一個難點,涉及到諸多執行緒的相互影響。對於多執行緒之間的相互影響,這個不在這個小栗子的闡述範圍內。這是除錯一個簡單的子程序中的子執行緒的小栗子。

使用材料

/*這是一個演示gdb除錯子程序、子執行緒的檔案
 */
#include <stdio.h>
#include <pthread.h>

void processSub();
void processMain();
void * threadSub(void *arg);

int main(int argc, const char *argv[])
{
    int pid;
    pid = fork();
    if
(pid<0) { exit(1); }else if(0==pid){ processSub(); }else{ processMain(); } return 0; } /*子程序處理函式 */ void processSub() { pid_t pid = getpid(); char prefix[] = "processSub main thread : "; pthread_t thread_id=pthread_self(); int tstatus; pthread_t pt; tstatus = pthread_create(&pt, NULL, threadSub, NULL); if
( tstatus != 0 ) { printf("processSub: Can not create new thread."); } printf("<%s pid=%lu,thread_id=%lu>\n", prefix, pid,thread_id); } /* 子程序的子執行緒處理函式 */ void * threadSub(void *arg) { pid_t pid = getpid(); pthread_t thread_id=pthread_self(); char prefix[] = "subprocess threadSub: "
; printf("<%s pid=%lu,thread_id=%lu>\n", prefix, pid,thread_id); return NULL; } /* 主程序處理函式 */ void processMain() { pid_t pid = getpid(); pthread_t thread_id=pthread_self(); char prefix[] = "processMain: "; printf("<%s pid=%lu,thread_id=%lu>\n", prefix, pid,thread_id); //在呼叫子程序之前,主程序不能執行完畢,退出 sleep(1000); }

除錯過程

1.生成除錯檔案

[root@localhost test]# gcc gdb_multi.c -g -O0 -Wall -lpthread
//顯示資訊
gdb_multi.c: 在函式‘main’中:
gdb_multi.c:13:5: 警告:隱式宣告函式‘fork’ [-Wimplicit-function-declaration]
     pid = fork();
     ^
...
gdb_multi.c:60:5: 警告:隱式宣告函式‘sleep’ [-Wimplicit-function-declaration]
     sleep(1000);
     ^

2.開始除錯

[root@localhost test]# gdb a.out 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/gch/test/a.out...done.

3.設定除錯子程序

(gdb) set follow-fork-mode child  //指定要除錯子程序
(gdb) set detach-on-fork off      //指定其他程序阻塞fork位置
(gdb) show follow-fork-mode //檢視設定的資訊
Debugger response to a program call of fork or vfork is "child".
(gdb) show detach-on-fork   //檢視設定的資訊
Whether gdb will detach the child of a fork is off.

4.斷點到子程序

(gdb) b 18
Breakpoint 1 at 0x4007ea: file gdb_multi.c, line 18.
(gdb) r
Starting program: /home/gch/test/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New process 13242]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7.x86_64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[Switching to Thread 0x7ffff7fea740 (LWP 13242)]

Breakpoint 1, main (argc=1, argv=0x7fffffffe5a8) at gdb_multi.c:18
18          processSub();
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7.x86_64
(gdb) s
processSub () at gdb_multi.c:28
28      pid_t pid = getpid();
(gdb) n
29      char prefix[] = "processSub main thread : ";
(gdb) 
30      pthread_t thread_id=pthread_self();
(gdb) 
34      tstatus = pthread_create(&pt, NULL, threadSub, NULL);

5.阻塞主執行緒除錯子執行緒

(gdb) set scheduler-locking on  //除錯時,阻塞其他執行緒
(gdb) show scheduler-locking 
Mode for locking scheduler during execution is "on".

6.檢視程序、執行緒資訊

(gdb) n
[New Thread 0x7ffff77fb700 (LWP 13244)]
35      if( tstatus != 0 )
(gdb) info thread           //檢視執行緒資訊
  Id   Target Id         Frame 
  3    Thread 0x7ffff77fb700 (LWP 13244) "a.out" 0x00007ffff78f4311 in clone () from /lib64/libc.so.6
* 2    Thread 0x7ffff7fea740 (LWP 13242) "a.out" processSub () at gdb_multi.c:35
  1    Thread 0x7ffff7fea740 (LWP 13238) "a.out" 0x00007ffff78bb291 in fork () from /lib64/libc.so.6
(gdb) info inferior         //檢視程序資訊
  Num  Description       Executable        
* 2    process 13242     /home/gch/test/a.out 
  1    process 13238     /home/gch/test/a.out 

7.切換到子執行緒並斷點子執行緒呼叫的函式

(gdb) thread 3
[Switching to thread 3 (Thread 0x7ffff77fb700 (LWP 13244))]
#0  0x00007ffff78f4311 in clone () from /lib64/libc.so.6
(gdb) b threadSub
Breakpoint 2 at 0x4008b3: threadSub. (2 locations)
(gdb) cont
Continuing.
Breakpoint 2, threadSub (arg=0x0) at gdb_multi.c:45
45      pid_t pid = getpid();
(gdb) n
46      pthread_t thread_id=pthread_self();
(gdb) 
47      char prefix[] = "subprocess threadSub: ";
(gdb) 
48      printf("<%s pid=%lu,thread_id=%lu>\n", prefix, pid,thread_id);
(gdb) 
<subprocess threadSub:  pid=13242,thread_id=140737345730304>
49      return NULL;
(gdb) q
A debugging session is active.

    Inferior 2 [process 13242] will be killed.
    Inferior 1 [process 13238] will be killed.

Quit anyway? (y or n) y
[root@localhost test]# 

ok!