每天学点GDB(四)

使用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

时间: 2024-11-18 01:58:31

每天学点GDB(四)的相关文章

10天学安卓-第四天

原文:10天学安卓-第四天 继续昨天的学习. 昨天我们根据取得的天气数据新建了一个视图用来显示各项内容,那么今天我们就把数据显示出来吧!!! 这里我们要把数据和视图联系起来,那么就用到了适配器-Adapter,Android给我们提供了很多Adapter,这里我们用到了BaseAdapter.   BaseAdapter(1) 右键点击src/com.demo.weather,选择 New > Class,按照下图填写: 选择[Finish]后,我们就新建了一个BaseAdapter的子类,打开

每天学点GDB(六)

<一>如何利用gdb对coredump进行分析 本篇主要讲解如何利用gdb对coredump进行分析 gdb ./demo core 查看调用堆栈 gdb)bt 查看更为完整的信息 gdb) bt full 如果是多线程,想看每个线程的调用堆栈 gdb) thread apply all bt 至于如何分析内存变量之类的,在本一系列前面的章节有专门论述,可以参考. 想调试已经在运行的程序 gdb ./demo 假设当前运行着的demo进程为1234,则在gdb中运行attach进行关联 gdb

《网络零售学》——第四章网络零售的基本规律与原理

第四章 网络零售的基本规律和原理 第一节 网络零售的经济学特征及基本理论 一.关于经济学基本原理 (一)经济学(economics) 经济学的定义:研究在资源稀缺和理性人假设下资源的合理配置:或者说经济学研究的是人在约束条件下的选择行为.经济学认为相对于人们的欲望,经济资源总是短缺的.经济学就是研究如何合理地配置和充分利用稀缺的经济资源来满足人们的多种需求的科学. 经济学的英语Economics是由希腊文οκο?[oikos]而来,意思是家庭.家族.财产权(family,household,es

跟我学XSL(四)

测试模式                   XML技术的优势之一就在于数据输出的可选择性,即选择需要的数据输出.前面我们所讲到的选择模式语句:<xsl:for-each>.<xsl:value-of>及<xsl:apply-template>只是简单的选取通过"/"符号层层到达的节点,如果我们对XML数据不需要全部输出,而只需要其中的满足某条件的部分数据,"萝卜青菜.各取所需",那么条件判断<xsl:if>与多条件判

坚持学asp.net——(四)

asp.net c#编程篇: c#编程我不怎么熟悉,既然教材里面有,就顺着它的思路学一下. 开始就讲什么变量.内存拉,看看就可以. 一.变量声明的问题: 1.习惯了vb,大小写是一个十分棘手的问题,又不得不这样做. 2.声明的时候可以同时赋值,也可以同时声明多个变量,为了写的程序好读,约定声明与赋值分离. 3.要想使用一个变量,必须提前声明. 4.给字符串变量提供值,必须使用双引号:给数字型变量提供值,就不需要使用任何引号.asp.net的语法中有双引号中的均被解释成文本,不在双引号中的均被解释

每天学点GDB(五)

使用GDB来进行STL容器的调试 现代C++中STL使用的越来越普遍,较之其它类型,stl容器类的调试显得复杂度更好.本篇以map为例说明如何利用gdb来遍历map中的各成员变量. 源码如下: #include <map> #include <iostream> #include <string> using namespace std; int main(int arg, char** argv) { map<int, string> mapExample

每天学点GDB(一)

<一>简单示例--Hello World 在Linux环境下进行C或是C++编程,调试工具首选GDB. GDB的功能很多,一下子全弄明白似乎不太可能.那么就从最简单的使用说起吧.一谈起简单,Helloworld就成了最佳的选择了. #include <stdio.h> #include <stdlib.h> 4 int main(int argc, char** argv) { printf("hello,world\n"); return 0; }

每天学点GDB(二)

<一>如何让将调试的内容保存到外部文件里面 在上一篇提及如何在断点处打印调试信息后,程序自动继续执行.本节主要讲述如何让将调试的内容保存到外部文件里面. 默认情况下,日志是没有打开的,所有的调试信息都会在屏幕中显示,即默认是输出到stdout中的.那么有没有可能将输出到屏幕中的内容保存到文件里呢.答案自然是肯定的,这里面有个地方遇要注意一下子,具体会在下面的示例中提及. 将日志文件打开,不指定文件名的话,默认的文件名是gdb.txt. gdb)set logging on 查看更多有关logg

每天学点GDB(三)

<一>强大的反汇编能力 GDB提供了强大的反汇编能力,本节就围绕于该主题而展开. 继续以Hello.c为例. 1 2 3 4 5 6 7 #include <stdlib.h> #include <stdio.h>   int main(int argc, char** argv) {   printf("hello,world\n");   return 0; } 编译生成可执行文件 gcc -o hello -g hello.c 用gdb载入进行