每天学点GDB 7

使用GDB进行多线程调试,查看互斥变量。

演示源码如下

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static void* thread_func(void* args);
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
int sum = 0;
#define MAX_NUM 10000

int main(int argc, char** argv) {
  int seq = 0;
  pthread_t thread_handle;
  for ( seq = 0; seq < 5; seq++) {
    int* tmp_seq = (int*)malloc(sizeof(int));
    *tmp_seq = seq;
    pthread_create(&thread_handle, NULL, thread_func, tmp_seq);
  }
  while ( 1 ) sleep(20);
  return 0;
}

static void* thread_func(void* args) {
  int thread_seq = *(int*)args;
  free(args);
  
  while ( 1 ) 
    {
      sleep(thread_seq + 2);
      pthread_mutex_lock(&g_mutex);
      if ( sum < MAX_NUM ) 
      sum++;
      else
    sum = 0;
      printf("in thread %d, sum is %d\n", thread_seq, sum);
      pthread_mutex_unlock(&g_mutex);
    }

}

编译

gcc -o demo -g demo.c -lpthread

运行效果如下

in thread 0, sum is 1
in thread 1, sum is 2
in thread 2, sum is 3
in thread 0, sum is 4
in thread 3, sum is 5
in thread 4, sum is 6
in thread 1, sum is 7
in thread 0, sum is 8
in thread 2, sum is 9

使用GDB进行调试

gdb ./demo
设置断点
gdb) br 32

查看运行的线程

gdb) info threads
 Id   Target Id         Frame 
  6    Thread 0xb5c9eb40 (LWP 914) "demo" 0xb7fdd416 in __kernel_vsyscall ()
  5    Thread 0xb649fb40 (LWP 913) "demo" 0xb7fdd416 in __kernel_vsyscall ()
  4    Thread 0xb6ca0b40 (LWP 912) "demo" 0xb7fdd416 in __kernel_vsyscall ()
  3    Thread 0xb74a1b40 (LWP 911) "demo" 0xb7fdd416 in __kernel_vsyscall ()
* 2    Thread 0xb7ca2b40 (LWP 910) "demo" thread_func (args=0x804a008) at demo.cpp:32
  1    Thread 0xb7ca4700 (LWP 906) "demo" 0xb7fdd416 in __kernel_vsyscall ()

查看当前线程的函数调用堆栈

gdb) bt full

查看哪个线程拥有互斥变量,首先需要知道pthread_mutex_t的具体结构是什么,

gdb) whatis g_mutex
type = pthread_mutex_t
gdb) set print pretty #让GDB输出效果排版的好看一些 gdb) ptype g_mutex type
= union pthread_mutex_t { pthread_mutex_t::__pthread_mutex_s __data; char __size[24]; long __align; }

打印出g_mutex的具体内容

gdb) p g_mutex
$2 = {
  __data = {
    __lock = 1, 
    __count = 0, 
    __owner = 910, 
    __kind = 0, 
    __nusers = 1, 
    {
      __spins = 0, 
      __list = {
        __next = 0x0
      }
    }
  }, 
  __size = "\001\000\000\000\000\000\000\000\216\003\000\000\000\000\000\000\001\000\000\000\000\000\000", 
  __align = 1
}

各位看官,注意上述输出中,owner表示当前拥有g_mutex的线程。

那么谁是910呢,上面用”info threads"只输出了1,2,3,4,5,6无法对应,ok. 用点top小技巧,

top -H -p 906

906表示demo的进程ID,-H表示打印出所有的线程。

当前拥有g_mutex是910,那么应该是第二号线程,即thread_seq为0的线程。

如果想在程序运行的时候知道当前线程中类似于top输出的pid值,可以通过如下方法。

/*#method 1*/
pid_t gettid(void);

/**************************************
*#method 2 using the following system call 
**************************************/

#include <sys/syscall.h>
pid_t tid = (pid_t) syscall (SYS_gettid);

 最后需要提醒的是,当设定断点停下来的时候,其它线程其实还是可以继续运行的。如果只想让当前线程可以运行,其它的全部停下来的话。请用下列的指令。

gdb) set scheduler-locking on

关于这个内容,可以参考链接http://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html

 转载时请注明出处,谢谢。

原文地址:https://www.cnblogs.com/hseagle/p/3040316.html