gdb调试跟踪代码

  1. 编译
    用gcc/g++编译源程序的时候,编译后的可执行文件不会包含源程序代码,如果要使用gdb调试的话,编译的时候要加 -g 的参数。
gcc test.c  -o test -g
  1. 调试
gdb test

常用命令:
(gdb)help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h
(gdb)run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r
(gdb)start:单步执行,运行程序,停在第一执行语句
(gdb)list:查看原代码(list-n,从第n行开始查看代码。list+ 函数名:查看具体函数),简写l
(gdb)set:设置变量的值
(gdb)next:单步调试(逐过程,函数直接执行),简写n
(gdb)step:单步调试(逐语句:跳入自定义函数内部执行),简写s
(gdb)backtrace:查看函数的调用的栈帧和层级关系,简写bt
(gdb)frame:切换函数的栈帧,简写f
(gdb)info:查看函数内部局部变量的数值,简写i
(gdb)finish:结束当前函数,返回到函数调用点
(gdb)continue:继续运行,简写c
(gdb)print:打印值及地址,简写p
(gdb)quit:退出gdb,简写q
(gdb)break+num:在第num行设置断点,简写b
(gdb)info breakpoints:查看当前设置的所有断点
(gdb)delete breakpoints num:删除第num个断点,简写d
(gdb)display:追踪查看具体变量值
(gdb)undisplay:取消追踪观察变量
(gdb)watch:被设置观察点的变量发生修改时,打印显示
(gdb)i watch:显示观察点
(gdb)enable breakpoints:启用断点
(gdb)disable breakpoints:禁用断点
(gdb)x:查看内存x/20xw 显示20个单元,16进制,4字节每单元
(gdb)run argv[1] argv[2]:调试时命令行传参
(gdb)set follow-fork-mode child#Makefile项目管理:选择跟踪父子进程(fork())

备注:
如果在gdb调试,出现 没有那个文件或目录,可以通过如下方式解决
在这里插入图片描述
进入gdb

(gdb) show debug-file-directory 
//查看当前的debug路径
(gdb) set debug-file-directory  
// 设置debug路径,这里为空。

gdb调试多线程
查看当前进程有多少线程:

(gdb) info threads

切换到对应的线程:

(gdb) thread 线程编号

gdb 提供了一个在调试时将程序执行流锁定在当前调试线程的命令选项——scheduler-locking 选项,这个选项有三个值,分别是 on、step 和 off,使用方法如下:

set scheduler-locking on 

用来锁定当前线程,只观察这个线程的运行情况, 当锁定这个线程时, 其他线程就处于了暂停状态,也就是说你在当前线程执行 next、step、until、finish、return 命令时,其他线程是不会运行的。

需要注意的是,你在使用 set scheduler-locking on/step 选项时要确认下当前线程是否是你期望锁定的线程,如果不是,可以使用 thread + 线程编号 切换到你需要的线程再调用 set scheduler-locking on/step 进行锁定。

set scheduler-locking step 

用来锁定当前线程,当且仅当使用 next 或 step 命令做单步调试时会锁定当前线程,如果你使用 until、finish、return 等线程内调试命令,但是它们不是单步命令,所以其他线程还是有机会运行的。相比较 on 选项值,step 选项值给为单步调试提供了更加精细化的控制,因为通常我们只希望在单步调试时,不希望其他线程对当前调试的各个变量值造成影响。

set scheduler-locking off 

用于关闭锁定当前线程。

<think>好的,我现在需要回答用户关于如何使用GDB调试Python代码的问题。首先,我得回忆一下GDB的基本用途,它主要是用于调试C/C++程序的,但用户想用它来调试Python代码。这可能涉及到Python的C扩展或者解释器本身的问题。 接下来,我应该考虑用户可能的场景。用户可能遇到了Python程序的崩溃,比如段错误(segmentation fault),这时候用普通的Python调试器(如pdb)可能无法捕捉到,因为问题可能出在底层的C扩展或者Python解释器。这时候GDB就显得有用了。 我需要分步骤解释如何使用GDB调试Python代码。首先,用户需要安装GDB和Python的调试符号。不同操作系统安装方式不同,比如Ubuntu可能需要安装python3-dbg或python-dbg包。然后,如何启动GDB附加到Python进程上,或者直接运行Python脚本。 然后,可能需要介绍一些常用的GDB命令,比如设置断点、查看堆栈、打印变量等。但要注意,Python代码和C代码在堆栈上的区别,用户可能需要切换上下文来查看Python层面的信息。 另外,PyEval_SetTrace这样的函数可以用来设置跟踪函数,帮助在Python代码中设置断点。或者使用gdb的Python扩展脚本,比如libpython.py,它提供了更多Python友好的命令,比如py-bt来查看Python堆栈。 可能还需要提到一些常见的调试场景,比如调试段错误,或者死锁问题。例如,当Python程序卡住时,用GDB获取线程信息,检查是否有锁未释放。 同时,需要提醒用户,GDB调试需要一定的C语言和Python内部机制的知识,对于普通Python代码问题,可能还是优先使用pdb或其他Python调试工具更高效。只有在涉及底层问题时,才需要使用GDB。 最后,要确保步骤清晰,语言通俗易懂,避免过多专业术语,或者如果使用术语,需要简单解释。比如解释什么是core dump,如何生成和分析。 可能还需要检查是否有遗漏的步骤,比如如何获取Python的调试符号,不同Linux发行版的包管理命令,或者如何在macOS上使用GDB(可能需要代码签名的问题)等。不过用户可能主要在Linux环境下使用,所以可以侧重Linux的步骤。 另外,可能提到一些工具,如faulthandler模块,它可以在程序崩溃时输出堆栈信息,辅助调试。或者结合coredump和GDB进行分析。 总结下来,回答的结构应该是: 1. 介绍GDB调试Python的适用场景(C扩展、解释器问题) 2. 安装必要的工具和调试符号 3. 启动GDB附加到Python进程 4. 常用GDB命令和技巧 5. 使用Python特定的GDB脚本(如libpython.py) 6. 示例调试步骤(比如处理段错误) 7. 注意事项和替代工具建议 需要确保每个步骤都简明扼要,用户能跟着操作。例如,具体如何安装python3-dbg,如何运行gdb --args python3 script.py,然后使用bt命令查看堆栈,py-list查看Python代码行等。 可能还需要指出,对于纯Python代码的问题,GDB并不是最佳选择,但对于底层问题非常有用。同时,调试时可能需要保持符号表,编译时的调试信息等。 最后,检查是否有错误,比如GDB命令的正确性,或者步骤是否合理,避免误导用户。</think>GDB调试Python代码主要用于分析底层问题(如C扩展崩溃、解释器死锁),以下是具体步骤和技巧: 1. 适用场景 - 段错误(Segmentation Fault) - Python解释器崩溃 - C扩展模块问题 - 死锁/线程问题 - 内存泄漏分析 2. 准备工作 ```bash # Ubuntu/Debian sudo apt-get install gdb python3-dbg # CentOS/RHEL sudo yum install gdb python3-debuginfo # macOS(需先安装Homebrew) brew install gdb codesign --entitlements gdb-entitlement.xml -fs gdb-cert $(which gdb) ``` 3. 基础调试流程 ```bash # 直接调试脚本 gdb --args python3 your_script.py # 附加到运行中的进程 gdb -p $(pgrep -f your_script.py) # 常用命令 (gdb) bt full # 查看完整堆栈 (gdb) info threads # 显示所有线程 (gdb) py-bt # 显示Python堆栈(需加载libpython) (gdb) py-list # 显示当前Python代码位置 ``` 4. 增强调试(使用libpython脚本) ```bash # 获取调试脚本 wget https://raw.githubusercontent.com/python/cpython/main/Tools/gdb/libpython.py # GDB中加载 (gdb) source libpython.py # 特殊命令 (gdb) py-up/py-down # 在Python堆栈帧间移动 (gdb) py-print x # 打印Python变量 (gdb) py-locals # 显示当前作用域变量 ``` 5. 段错误调试示例 ```python # test.py import ctypes ctypes.string_at(0) # 人为制造段错误 ``` 调试过程: ```bash $ gdb --args python3 test.py (gdb) r # 出现段错误后 (gdb) bt full (gdb) py-bt (gdb) info registers ``` 6. 线程死锁调试 ```python # deadlock.py import threading lock = threading.Lock() lock.acquire() lock.acquire() # 第二次获取会死锁 ``` 调试步骤: ```bash $ gdb -p $(pgrep -f deadlock.py) (gdb) info threads (gdb) thread 2 (gdb) py-bt (gdb) py-list ``` 7. 内存分析技巧 ```bash (gdb) malloc_info 0 stdout # 显示内存分配情况 (gdb) py-bt 10 # 显示最近10个Python调用 (gdb) dump binary memory dump.bin 0x0000555555a00000 0x0000555555c00000 ``` 8. 替代方案建议 - 常规调试优先使用pdb: ```bash python3 -m pdb your_script.py ``` - 输出崩溃堆栈: ```python import faulthandler faulthandler.enable() ``` - 内存分析工具:Valgrind、tracemalloc - 性能分析:cProfile、py-spy 注意事项: 1. 生产环境调试可能影响性能 2. 需要保持调试环境与生产环境一致 3. 部分Python优化版本(如--with-pydebug)会提供更多调试信息 4. 解释器内部函数名通常以_Py或Py开头 通过GDB调试可以深入分析以下问题: - C扩展中的非法内存访问 - 引用计数错误 - GIL竞争问题 - Python对象内存布局 - 解释器字节码执行异常 建议结合core dump文件进行分析: ```bash ulimit -c unlimited ./crash_script.py # 生成core文件 gdb python3 core # 加载core dump ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值