首页 > g-gdb 调试多线程

g-gdb 调试多线程

代码调试工具gdb是一个能够让我们在工作中高效排查代码异常根源的利器。

在此将gdb针对多线程的调试方式做一个笔记,也方便后续回顾以及分享大家。

本文采用的是一个简单的多线程代码示例,同时调试是在mac上进行的

mac安装gdb brew install gdb即可

基本命令介绍

开始之前先简单介绍几个gdb调试多线程的子命令

  • layout next 开启子窗口,显示当前程序运行所在的源码位置
  • b xxx 在某一行,或者某一个函数处增加断点
  • info b 查看断点信息
  • r 运行程序
  • info threads 查看当前可调试的所有线程信息
  • where 查看进程运行到当前位置的函数调用栈信息
  • thread num 调试状态切换到线程num
  • break thread_test.cc:123 thread all 在所有线程中相应的行上设置断点
  • thread apply all id1 id2 command 让一个或者多个线程执行GDB命令
  • thread apply all command 让所有被调试线程执行gdb命令 command
  • watch variable 在断点当前位置增加变量的variable的监控信息,后续运行的时候会打印
  • c 继续运行,直到遇到断点停顿

示例1

目标:在不加锁的情况下,多个线程的运行交叉运行的,导致进程内部共享的变量对外的体现不是连续的。

代码如下

#include 
#include 
#include using namespace std;static int g_a = 0;void pthread_func1() { for (int i = 1;i < 5000; ++i) { g_a ++;}
}void pthread_func2() { for (int i = 5000;i < 10000; ++i) { g_a ++;}
}int main() { thread t1(pthread_func1);thread t2(pthread_func2);t1.join();t2.join();return 0;
}

编译:

g++ -std=c++11 -g pthread_test.cc -o pthread_test -pthread

调试过程如下:

在这里插入图片描述

通过以上调试我们可以发现在当前进程中的变量g_a每运行一次并不是累加1,可能会累加2,而且代码的跳转也能发现其实是多个线程交替执行。

基本的调试方式也就是使用我们已经说过的线程相关调试命令了。

示例2

目标:在加锁的情况下,我们的进程全局变量的访问变成了串行方式

测试代码如下:

#include 
#include 
#include using namespace std;mutex g_lock;
static int g_a = 0;void pthread_func1() { for (int i = 1;i < 5000; ++i) { g_lock.lock();g_a ++;g_lock.unlock();}
}void pthread_func2() { for (int i = 5000;i < 10000; ++i) { g_lock.lock();g_a ++;g_lock.unlock();}
}int main() { thread t1(pthread_func1);thread t2(pthread_func2);t1.join();t2.join();return 0;
}

编译调试过程如下:

在这里插入图片描述

此时可以看到我们加了mutex的锁之后对于整个进程来说,执行一次变量只会加一,显然满足了全局变量状态变化的逻辑

总结

源代码以及运行过程中各个线程的子变量信息实时显示,且通过断点 我们清楚得看到了代码运行过程中的跳转逻辑,可以说解决问题的效率事半功倍了。

更多相关:

  • 多线程有什么好处?提高CPU的利用率,更好地利用系统资源,使用Monitor类可以同步静态/实例化的方法的全部代码或者部分代码段,使用不同的同步类创建自己的同步机制。多线程指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程提升整体处理性能。多线程是指程序中包含多个执行流,即...

  • Step1:在界面主函数的构造函数中初始化多线程 auto mythread = new QThread(); //新建connect(mythread , &QThread::finished, mythread, &QObject::deleteLater);//线程运行结束后释放内存object1->moveToThread...

  • 一、thread的基本用法 参见C++使用thread类多线程编程 。 二、类外使用多线程,访问类的成员 这几种方式,新建线程都是在类外,然后通过把友元函数或者成员函数作为thread参数。 #include #include #include using namesp...

  • 本博文是根据中科大信息学院谭立湘老师的课件加上自己的理解整理出来的 ************************************************************************************ NVIDIA在2007年推出CUDA这个统一计算架构 CUDA的基本思想是支持大量的线程级并...

  • 一、parallel communication patterns   并行通信模式 Map:映射,在特定的位置读取和写入。 Gather:收集,从多个不同的位置读入,写入一个位置。 Scatter:分发,写入多个位置。 Transpose转置 结构数组缩写为AOS,数组结构缩写为SOA 转置运算是指任务重新排序内存中的数...