多线程调试必杀技 - GDB的non-stop模式
开源的GDB被广泛使用在Linux、OSX、Unix和各种嵌入式系统(例如手机),这次它又带给我们一个惊喜。
多线程调试之痛
调试器(如VS2008和老版GDB)往往只支持all-stop模式,调试多线程程序时,如果某个线程断在一个断点上,你的调试器会让整个程序freeze,直到你continue这个线程,程序中的其他线程才会继续运行。这个限制使得被调试的程序不能够像真实环境中那样运行--当某个线程断在一个断点上,让其他线程并行运行。
GDBv7.0引入的non-stop模式使得这个问题迎刃而解。在这个模式下,
- 当某个或多个线程断在一个断点上,其他线程仍会并行运行
- 你可以选择某个被断的线程,并让它继续运行
让我们想象一下,有了这个功能后
- 当其他线程断在断点上时,程序里的定时器线程可以正常的运行了,从而避免不必要得超时
- 当其他线程断在断点上时,程序里的watchdog线程可以正常的运行了,从而避免嵌入式硬件以为系统崩溃而重启
- 可以控制多个线程运行的顺序,从而重现deadlock场景了。由于GDB可以用python脚本驱动调试,理论上可以对程序在不同的线程运行顺序下进行自动化测试。
因此,non-stop模式理所当然成为多线程调试“必杀技”。这2009年下半年之后发布的Linux版本里都带有GDBv7.0之后的版本。很好奇,不知道VS2010里是不是也支持类似的调试模式了。
演示GDB的non-stop模式
让破砂锅用一个C++小程序在Ubuntu Linux 09.10下demo这个必杀技。虽然我的demo使用命令行版gdb,如果你喜欢图形化的调试器,Eclipse2009年5月之后的版本可以轻松的调 用这个功能,详情参见Eclipse参见http://live.eclipse.org/node/723
1. 编译以下程序nonstop
1 // gdb non-stop mode demo 2 // build instruction: g++ -g -o nonstop nonstop.cpp -lboost_thread 3 4 #include <iostream> 5 #include <boost/thread/thread.hpp> 6 7 struct op 8 { 9 op(int id): m_id(id) {} 10 11 void operator()() 12 { 13 std::cout << m_id << " begin" << std::endl; 14 std::cout << m_id << " end" << std::endl; 15 } 16 17 int m_id; 18 }; 19 20 int main(int argc, char ** argv) 21 { 22 boost::thread t1(op(1)), t2(op(2)), t3(op(3)); 23 t1.join(); t2.join(); t3.join(); 24 return 0; 25 } 26
2. 把一下3行添加到~/.gdbinit来打开non-stop模式
set target-async 1 set pagination off set non-stop on
3. 启动gdb,设断点,运行.可以看到主线程1是running,3个子线程都断在断点上,而不是只有一个子线程断在断点上.
~/devroot/nonstop$ gdb ./nonstop GNU gdb (GDB) 7.0-ubuntu Reading symbols from /home/frankwu/devroot/nonstop/nonstop...done. (gdb) break 14 Breakpoint 1 at 0x402058: file nonstop.cpp, line 14. (gdb) break 24 Breakpoint 3 at 0x401805: file nonstop.cpp, line 24. (gdb) run Starting program: /home/frankwu/devroot/nonstop/nonstop [Thread debugging using libthread_db enabled] [New Thread 0x7ffff6c89910 (LWP 2762)] [New Thread 0x7ffff6488910 (LWP 2763)] 1 begin Breakpoint 1, op::operator() (this=0x605118) at nonstop.cpp:14 14 std::cout << m_id << " end" << std::endl; 2 begin Breakpoint 1, op::operator() (this=0x605388) at nonstop.cpp:14 14 std::cout << m_id << " end" << std::endl; [New Thread 0x7ffff5c87910 (LWP 2764)] 3 begin Breakpoint 1, op::operator() (this=0x605618) at nonstop.cpp:14 14 std::cout << m_id << " end" << std::endl; (gdb) info threads 4 Thread 0x7ffff5c87910 (LWP 2764) op::operator() (this=0x605618) at nonstop.cpp:14 3 Thread 0x7ffff6488910 (LWP 2763) op::operator() (this=0x605388) at nonstop.cpp:14 2 Thread 0x7ffff6c89910 (LWP 2762) op::operator() (this=0x605118) at nonstop.cpp:14 * 1 Thread 0x7ffff7fe3710 (LWP 2759) (running)
4. 让线程3继续运行,注意我顾意把主线程1也continue,这是我发现的workaround,否则gdb不能切回thread 1.
(gdb) thread apply 3 1 continue
Thread 3 (Thread 0x7ffff6488910 (LWP 2763)): Continuing.
Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)): Continuing. Cannot execute this command while the selected thread is running. 2 end [Thread 0x7ffff6488910 (LWP 2763) exited]
warning: Unknown thread 3.
Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)): Continuing. Cannot execute this command while the selected thread is running. (gdb) info threads 4 Thread 0x7ffff5c87910 (LWP 2764) op::operator() (this=0x605618) at nonstop.cpp:14 2 Thread 0x7ffff6c89910 (LWP 2762) op::operator() (this=0x605118) at nonstop.cpp:14 * 1 Thread 0x7ffff7fe3710 (LWP 2759) (running)
5. 让另外两个线程继续运行而结束,主线程断在第24行,最后结束.
(gdb) thread apply 4 2 1 continue
Thread 4 (Thread 0x7ffff5c87910 (LWP 2764)): Continuing.
Thread 2 (Thread 0x7ffff6c89910 (LWP 2762)): Continuing.
Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)): Continuing. Cannot execute this command while the selected thread is running. 3 end 1 end [Thread 0x7ffff5c87910 (LWP 2764) exited] [Thread 0x7ffff6c89910 (LWP 2762) exited]
Breakpoint 3, main (argc=1, argv=0x7fffffffe348) at nonstop.cpp:24 24 return 0; (gdb) continue Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)): Continuing.
Program exited normally.
参考资料
Reverse Debugging, Multi-Process and Non-Stop Debugging Come to the CDT
多线程调试必杀技 - GDB的non-stop模式的更多相关文章
- GDB 多线程调试:只停止断点的线程,其他线程任然执行; 或只运行某些线程 其他线程中断
多线程调试之痛 调试器(如VS2008和老版GDB)往往只支持all-stop模式,调试多线程程序时,如果某个线程断在一个断点上,你的调试器会让整个程序freeze,直到你continue这个线程,程 ...
- [转] linux下的c/c++调试器gdb
PS:1. 断点C++类函数,用b 命名空间::类名::方法名 2. 编译参数一定要加-g,才可断点调试 http://www.cnblogs.com/xd502djj/archive/2012/08 ...
- linux下的c/c++调试器gdb
Reference: http://www.cnblogs.com/xd502djj/archive/2012/08/30/2663960.html linux下的c/c++调试器gdb gdbLi ...
- [skill][gdb] gdb 多线程调试
中文快速入门: http://coolshell.cn/articles/3643.html (关于多线程的部署说的并不太对) 进阶: 多进程相关概念: inferiors 是什么? http://m ...
- GDB常用调试命令以及多进程多线程调试
http://blog.csdn.net/freeelinux/article/details/53700266 一:普通命令 1.list命令 list linenum 显示程序第l ...
- gdb 多线程调试
gdb 多线程调试 http://hi.baidu.com/hcq11/blog/item/9f5bfc6e696209d680cb4a25.html http://hi.baidu.com/lit ...
- GDB多线程调试
一.多线程调试1. 多线程调试,最重要的几个命令:info threads 查看当前进程的线程. ...
- Linux系统编程@多线程与多进程GDB调试
博客内容参考自 http://www.cnblogs.com/xuxm2007/archive/2011/04/01/2002162.html http://blog.csdn.net/pbymw8i ...
- 利用GDB进行多线程调试
一.多线程调试 多线程调试重要就是下面几个命令: info thread 查看当前进程的线程. thread <ID> 切换调试的线程为指定ID的线程. break file.c:100 ...
随机推荐
- linux tomcat 突然验证码出不来
情况描述 虚拟机上用tomcat部署的web应用,本来都还可以的.后来打了一个快照进行过压缩后,重新起虚拟机发现应用登录界面的验证码出不来了,具体报的是500错误. 参见http://www.blog ...
- eclipse导入/导出项目要注意三个地方
这个三个地方的jdk必须保持一致,不报错
- luogu P3393 逃离僵尸岛
luoguP3393逃离_僵尸岛_ 一道洛谷不知道哪门子月赛的题 可以用此题来练习最短路算法 SPFA和dijkstra的练习题(关于Floyed,他死了 思路: 本题是最短路板子. 首先就是建立虚点 ...
- HTML5 Differences from HTML4
Abstract "HTML5 Differences from HTML4" describes the differences of the HTML5 specificati ...
- (四)Jsoup 获取 DOM 元素属性值
第一节: Jsoup 获取 DOM 元素属性值 Jsoup获取DOM元素属性值 比如我们要获取博客的href属性值: 我们这时候就要用到Jsoup来获取属性的值 : 我们给下示例代码: package ...
- 编程六月定律 | 外刊IT评论网
编程六月定律 上周,我被迫对一个很老的项目做一些修改.麻烦是,当开始着手时,我真的记不清这个项目究竟有多老了. 这实际上是我使用Codeigniter实现的第一个MVC项目.打开项目文件后,很多东西都 ...
- 一步一步学习IdentityServer3 (11) OAuth2
OAuth中定义了四个Role 资源所有者:这里可以理解为一个用户 资源服务器:如同前面章节中的 Web站点或者WebApi 服务资源站点 客户端:这里是Client,如同Identityserver ...
- android拾遗——Android之Notification和NotificationManager
1.使用系统自带的Notification //创建一个NotificationManager的引用 String ns = Context.NOTIFICATION_SERVICE; Notific ...
- ViewPager中的子Activity无法响应OnActivityResult的解决方法
ViewPager子Activity通过startActivityForResult()跳转至OtherActivity,OtherActivity回传结果由ViewPager所在的父Activity ...
- STL容器读书笔记
vector vector维护的是一个连续线性空间 vector是动态空间,随着元素的加入会自动扩容,扩充至当前size的两倍,然后将原内容拷贝,开始在原内容之后构造新元素,并释放空间 vector提 ...