GDB多线程调试和死锁

2023-05-16

set schedular-locking on / off

条件断点查看循环中的某些变量

break if命令

示例:break test.c:34 if (x & y) == 1
默认情况下我们执行到断点处继续执行时,所有线程都会运行。想要控制只有当前线程运行可用上面命令的on实现。

#include <iostream>
#include <thread>
#include <chrono>

void thread1func()
{
    while(1)
    {
        std::cout << "this is thread1, ID: " << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void thread2func()
{
    while(1)
    {
        std::cout << "this is thread2, ID: " << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}


int main()
{
    std::thread thd1(thread1func);
    std::thread thd2(thread2func);

    std::cout << "this is main thread" << std::endl;

    thd1.join();
    thd2.join();

    return 0;
}

// 编译要添加-g选项
运行程序,命令行查看:

ps -aux / -ef | grep xxx 查看当前运行的进程

[root@localhost ~]# ps -aux | grep a.out
root 4360 0.0 0.1 31240 1108 pts/0 Sl+ 17:20 0:00 ./a.out
root 4366 0.0 0.1 112728 1004 pts/1 S+ 17:21 0:00 grep --color=auto a.out

ps -aL | grep xxx 查看当前运行的轻量级进程(线程)

[root@localhost ~]# ps -aL
PID LWP TTY TIME CMD
4360 4360 pts/0 00:00:00 a.out
4360 4361 pts/0 00:00:00 a.out
4360 4362 pts/0 00:00:00 a.out
4367 4367 pts/1 00:00:00 ps
[root@localhost ~]# ps -aL | grep a.out
4360 4360 pts/0 00:00:00 a.out
4360 4361 pts/0 00:00:00 a.out
4360 4362 pts/0 00:00:00 a.out

pstree -p 主线程id 查看主子线程的关系

[root@localhost ~]# pstree -p 4360
a.out(4360)─┬─{a.out}(4361)
└─{a.out}(4362)
[root@localhost ~]#
线程栈结构的查看

pstack 4360(主线程id)

gdb查看线程信息

gdb attach 主线程id 将进程附加到gdb中,可以看到创建了两个子线程

[root@localhost ~]# gdb attach 4360
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7
Copyright © 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/…
attach: 没有那个文件或目录.
Attaching to process 4360
Reading symbols from /home/code/cpp考察点/gdb多线程/a.out…(no debugging symbols found)…done.
Reading symbols from /lib64/libpthread.so.0…(no debugging symbols found)…done.
[New LWP 4362]
[New LWP 4361]
[Thread debugging using libthread_db enabled]
Using host libthread_db library “/lib64/libthread_db.so.1”.
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/libstdc++.so.6…(no debugging symbols found)…done.
Loaded symbols for /lib64/libstdc++.so.6

查看线程的一些信息

(gdb) info inferiors # 查看进程
Num Description Executable

  • 1 process 4360 /home/code/cpp考察点/gdb多线程/a.out
    (gdb) info threads # 查看线程
    Id Target Id Frame
    3 Thread 0x7fc93ccbb700 (LWP 4361) “a.out” 0x00007fc93cd80e2d in nanosleep () from /lib64/libc.so.6
    2 Thread 0x7fc93c4ba700 (LWP 4362) “a.out” 0x00007fc93cd80e2d in nanosleep () from /lib64/libc.so.6
  • 1 Thread 0x7fc93dcd3740 (LWP 4360) “a.out” 0x00007fc93d8b0f47 in pthread_join () from /lib64/libpthread.so.0
    (gdb) bt # 查看线程栈结构
    #0 0x00007fc93d8b0f47 in pthread_join () from /lib64/libpthread.so.0
    #1 0x00007fc93d655e37 in std::thread::join() () from /lib64/libstdc++.so.6
    #2 0x000000000040120b in main ()
    (gdb) thread 2 # 切换线程
    [Switching to thread 2 (Thread 0x7fc93c4bathread apply all700 (LWP 4362))]
    #0 0x00007fc93cd80e2d in nanosleep () from /lib64/libc.so.6
    (gdb) thread 3
    [Switching to thread 3 (Thread 0x7fc93ccbb700 (LWP 4361))]
    #0 0x00007fc93cd80e2d in nanosleep () from /lib64/libc.so.6
    (gdb)
    gdb调试多线程

设置断点

设置断点 break 行号/函数名

查看断点 info b

执行线程2的函数,执行完毕继续运行到断点处

继续使某线程运行 thread apply 1-n(第几个线程) n

(gdb) break thread1func()
Breakpoint 1 at 0x401101: file main.cc, line 9.
(gdb) thread apply 2 n
只运行当前线程

(gdb) set scheduler-locking on
(gdb) c
所有线程并发执行

(gdb) set scheduler-locking off
(gdb) c
gdb定位死锁

  1. thread apply all bt 打印所有线程的堆栈信息,观察哪些线程栈卡在lock_wait或者类似调用上,说明这几个线程极有可能产生死锁
  2. 利用thread ID命令切换到怀疑的线程,打印锁的信息,比如查看线程3,并打印堆栈信息
  3. 可以看到堆栈最终卡在源码中的第53行,堆栈的第7层,我们使用frame命令查看第7层具体信息
    (gdb) frame 7
    #7 0x000000000040183f in DataPool::pushToPool (this=0xeab058, inputData=std::shared_ptr (count 2, weak 0) 0x7fdc480008c0) at deadlock.cpp:53
    53 std::unique_lockstd::mutex lckTwo(mutexTwo_);
    (gdb)
  4. 查看一下lckTwo这把锁和mutexTwo_的信息,Owner字段表示哪个线程持有这把锁,它是线程的lwp号,可以通过info threads查看。
    (gdb) p lckTwo
    $1 = {_M_device = 0xeab098, M_owns = false}
    (gdb) p mutexTwo

    $2 = {std::__mutex_base = {_M_mutex = {__data = {__lock = 2, __count = 0, __owner = 18736, __nusers = 1, __kind = 0, __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}},
    __size = “\002\000\000\000\000\000\000\000\060I\000\000\001”, ‘\000’ <repeats 26 times>, __align = 2}}, }
    (gdb)
    #这里我们可以看到线程3当前没有拥有lckTwo这把锁,互斥量mutexTwo_当前被lwp号为18736的线程占有,即线程2,那么这个时候我们就找到了死锁的具体点,通过审查线程2执行的代码,死锁很快就能定位出来。我们这段代码是有意地构造死锁条件,进行逆推。不过真实开发中出现的死锁问题,也可以通过gdb调试结合core dump分析来解决。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GDB多线程调试和死锁 的相关文章

随机推荐

  • python类初始化详解_Python C头文件解析和反向初始化

    我有兴趣使用Python以递归方式解析C头文件 只有结构和变量声明 Python C头文件解析和反向初始化 这是我正在寻找的一个例子 假设如下 xff1a typedef struct double value 3 vector3 type
  • excel vba编程代码大全_实战VBA代码一键提取EXCEL中的所有公式!

    有的时候 xff0c 我们希望把表中的公式提取出来 xff0c 进行保存 xff01 少量 xff0c 我们可以手动复制 xff0c 量大 xff0c 猝 所以我们今天就分享一下如何一键提取 用什么 xff0c VBA上吧 xff01 还是
  • linux系统备份路径,linux系统备份恢复到本机或是别的机器上

    最近一直搞Xtion2 openni2 一下装完一个东西就不能用了 xff0c 由于ubuntu系统不熟 xff0c 找不到错误 xff0c 弄得每次都要重新装系统 xff0c 当我配了好几天的系统 xff0c 里面带着mxnet orbs
  • cmake之 ADD_LIBRARY()

    上一篇我分析了如何调用别人的第三方库 xff0c 现在我继续分析如何构建一个库供他人使用 完成这个任务需要用到ADD LIBRARY 强烈建议学习cmake的同学多多参考官方文档 xff0c 自己也是参考了一部分 1 xff1a ADD L
  • ESB企业服务总线

    ESB企业服务总线 提供位置透明性的消息路由和寻址服务提供服务注册和命名的管理功能支持多种消息传递范性支持多种可以广泛使用的传输协议支持多种数据格式及其相互转换提供日志和监控功能
  • 对Nginx的简单理解

    Nginx 同行是apache nginx同apache一样都是一种web服务器 xff0c 基于rest架构风格 xff0c 以统一资源描述符URI或者统一资源定位符URL作为沟通依据 xff0c 通过HTTP协议提供各种网络服务 apa
  • VSCode+clangd阅读linux内核源码

    1 clangd 原理介绍 clangd 插件用于代码语义分析 代码补全 跳转等 能做到代码精准跳转 精准自动补全 xff0c 其根本原理是通过读取工程编译自动生成的compile commands json 文件来索引其中包含的源文件和关
  • 旋转矩阵、欧拉角

    旋转矩阵 欧拉角 注 xff1a 下面为学习空间机器人技术系列课程笔记 xff0c 加上一些自己的整理 xff0c 方便复习 一 旋转矩阵的引出 下面坐标系0的基向量为 x 0 xff0c
  • Makefile的入门完整教程(包学包会)

    Makefile的完整入门教程 xff08 实现不了来打我TAT xff09 看完能够了解Makefile是什么 xff1b 我们能用makefile做什么 xff1b makefile的简易使用 1 什么是Makefile Makefil
  • ubuntu18.04 升级内核后,进入系统页面卡在“started gnome display manager“的解决方案

    问题描述 安装了18 04后 xff0c 系统的内核是5 0的 xff0c 不支持电脑的wifi xff0c 所以就想升级一下 升级到5 4后在grub界面选择5 4的内核后 xff0c 进入系统 xff0c 界面一直卡在started g
  • Ubuntu 14.04下,分辨率只有800×600的解决方法

    对于Ubuntu 14 04 xff0c 在安装好后 xff0c 默认的分辨率是800 600 xff0c 对于有着高分辨率例如1920 1080的显示器 xff0c 或者想要拓展双屏 xff0c 本身默认显示器驱动无法实现 xff0c 因
  • ubuntu14.04下安装cmake 3.5

    对于ros的应用 xff0c 很多还局限在indigo下 xff0c 因此要求的Ubuntu版本还限制在14 04 但对于很多新的功能包 是在kinetic下运行的 xff0c 很多cmake要求在3 5以上 xff0c 而安装ros in
  • Ubuntu16.04下使用ros_qtc_plugin在qt下进行编译

    系统测试环境 系统版本 Ubuntu16 04ROS版本 kinetic 按照官网的教程https ros qtc plugin readthedocs io en latest source Improve ROS Qt Creator
  • Ubuntu16.04下openpose编译及测试demo

    一 安装 官方安装流程见openpose官方 在安装前 xff0c 尽量保证有很好的显卡以及内存 xff0c 不然在运行demo的过程中会出现out of memory的情况出现 流程如下 xff1a 1 下载 git clone http
  • ubuntu16.04 通过anaconda建立虚拟环境,安装tensorflow1.10,cuda9.0,cudnn7.1.2

    1 anaconda建立虚拟环境及conda操作 env name代表你想要建立的环境名字 n表示名字 conda create n env name python 61 3 5 激活环境 source activate env name
  • 运维人员核心职责

    运维小知识点 xff01 网站数据不能丢网站7 24小时运转提升用户体验 xff0c 访问速度要快 云计算 1 公有云 2 私有云 就是自己内部的运维工程师部署的一个云平台 xff0c 资源管理平台数据都放在自己手中 xff0c 不被别人看
  • Ubuntu16.04下向github传送或修改代码

    初次使用Git设置 这段针对的是初次使用Git的设置 xff0c 如果初次设置之后 xff0c 就直接跳到下一阶段 将本地仓库push至github远程仓库 1 首先要确定Ubuntu下是否有git 终端运行指令 sudo apt inst
  • 字符串尾部得加'\0'原因

    39 0 39 一般放在字符串的结束处 xff0c 表示字符串的结束 xff0c 其是ascii值为0的字符的转义 在头文件 include lt string h gt 中包含的一些字符串处理函数等中 xff0c 一般处理字符串时 xff
  • cmake-CMakeLists.txt中添加目标编译选项的方法

    CMakeLists txt中添加目标编译选项的方法 原因 xff1a 如果程序中用到了宏来区分不同的方法 xff0c 但是又不想每次在用到不同的方法的时候都要在程序中更改宏定义后再进行编译 xff0c 那么可以在CMakeLists tx
  • GDB多线程调试和死锁

    set schedular locking on off 条件断点查看循环中的某些变量 break if命令 示例 xff1a break test c 34 if x amp y 61 61 1 默认情况下我们执行到断点处继续执行时 xf