调试技巧:多线程调试

我们给智能体编程的时候,不同的元件往往是同时运行的,在实际的多线程实现上可能是轮询,可能是更复杂的事件循环、实时系统……
传统的裸机断点,在一处停下后,其他元件全都会跟着停摆,我们就不能观察单个元件停止的现象。
比如,机器人的摄像头、雷达、编码器、电机照常工作,只是负责关键帧的元件暂停给关节发目标角度,我们就能看到机器人“定住”是什么样子

1 裸机大循环

• 自己写 while(1) 模拟调度,芯片只有一个线程,调试器只能全部暂停。
• 解决:给每个模块加一个 enable 开关(代码级隔离)。调试时把 arm_enable=0,其余代码继续跑,MCU 时间不停。但我们只能屏蔽一整个函数,函数里面没有跳出执行,也没有堆栈还原执行。

2 RTOS

• 直接把任务优先级临时降到 0(vTaskPrioritySet(handle, 0)),或者干脆 vTaskSuspend(handle)
• 在 IDE 里给该任务函数打断点,其余任务继续被调度。
• 中断仍可能打断,必要时在 vPortEnterCritical() 里短暂关中断)

3 GDB POSIX thread

GDB Non-Stop Mode
Asynchronous and non-stop modes (Debugging with GDB)
Non-Stop Mode (Debugging with GDB)
Threads (Debugging with GDB)

GDB non-stop模式 - 面具下的戏命师 - 博客园
多线程调试之痛 GDB 多线程调试:只停止断点的线程,其他线程任然执行; 或只运行某些线程 其他线程中断 - LiuYanYGZ - 博客园
多线程调试必杀技 - GDB的non-stop模式 - 向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除 - 赢在IT,Playin' with IT,Focus on Killer Application,Marketing Meets Technology.
Multi-threaded RTOS debug | CLion Documentation

• 任务/线程是调试器能识别的调度单元,它源自<pthread.h>,定义在libthread_db。
set non-stop on,调试器只会挂起指定任务,其余继续。

4 RTOS POSIX Thread

FreeRTOS - FreeRTOS-Plus-POSIX pthread.h Implementation - FreeRTOS™
ESP-IDF - POSIX 支持(包括 POSIX 线程支持) - ESP32 - — ESP-IDF 编程指南 v5.4.2 文档
Zephyr - Zephyr RTOS SMP 使用 GDB 不间断模式进行 IoT Edge 设备的调试 |马凯码
RT-Thread - 16.POSIX接口 - Pthreads简介 - 《RT-Thread编程手册》 - 书栈网 · BookStack

如果给RTOS引入POSIX兼容层,则GDB的non-stop可以直接识别到RTOS的线程。

5 Debugpy Thread

multiprocessing是进程,threading是线程,asyncio是协程。vscode的debugpy可以直接调试
vscode python 多进程,多线程,带参数调试_vscode多线程调试-CSDN博客
Pasted image 20250717193341.png

6 ROS Node

(48 封私信 / 80 条消息) vscode下调试ROS项目,节点调试,多节点调试,roslauch调试 - 知乎

调试技巧:变量监测

把所有调试信息放进printf是最粗暴的做法,实际上大多数调试器都有变量查看器

调试技巧:单元测试

单元测试,其实正好可以写在if __name__ == '__main__'

可以说,软件单元测试就是软件世界的“仿真激励”(TestBench)。它们都是为了同一个目的:隔离一个“单元”(一个模块/一个类/一个函数),给它施加特定的“激励输入”(函数参数/方法调用),然后捕获其“输出响应”(返回值/状态改变),并与“预期结果”进行比较,以验证其行为是否正确。