文档章节

运行时调试-关于死循环

a
 alex_wei
发布于 2013/07/01 17:43
字数 626
阅读 573
收藏 0
对于正在运行的程序,使用gdb attach功能进行运行时调试(启动gdb后使用attach <PID>命令或在启动gdb时使用-p <PID>参数)。
以下是一段故意构造的简单死循环程序:
#include <stdio.h>
#include <unistd.h>
int main()
{
    int i;
    for (i = 0; ; ++i) {
        printf("%d\n", i);
        sleep(1);
    }
}

使用gcc -O2编译程序后运行,并在另一个虚拟终端里使用gdb attach进程:

root@bt:~# gdb -q -p 2569
Attaching to process 2569
Reading symbols from /root/test3...(no debugging symbols found)...done.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007fbf605ac380 in nanosleep () from /lib/libc.so.6
(gdb) bt
#0 0x00007fbf605ac380 in nanosleep () from /lib/libc.so.6
#1 0x00007fbf605ac210 in sleep () from /lib/libc.so.6
#2 0x00000000004005c8 in main ()
(gdb) finish
Run till exit from #0 0x00007fbf605ac380 in nanosleep () from /lib/libc.so.6
0x00007fbf605ac210 in sleep () from /lib/libc.so.6
(gdb) finish
Run till exit from #0 0x00007fbf605ac210 in sleep () from /lib/libc.so.6
0x00000000004005c8 in main ()
(gdb) ni
0x00000000004005a8 in main ()
(gdb)
0x00000000004005aa in main ()
(gdb)
0x00000000004005af in main ()
(gdb)
0x00000000004005b4 in main ()
(gdb)
0x00000000004005b6 in main ()
(gdb)
0x00000000004005b9 in main ()
(gdb)
0x00000000004005be in main ()
(gdb)
0x00000000004005c3 in main ()
(gdb)
0x00000000004005c8 in main ()
(gdb)
0x00000000004005a8 in main ()
(gdb)
0x00000000004005aa in main ()
...
attach会使进程挂起,现象类似于插入了一个临时断点。上面的操作中使用了两次finish命令使程序运行至返回到main()函数中。

对于使用-O2选项编译的程序,无法简单的进行源代码级别的调试,next/step命令不可用。对于此类程序,可以使用nexti/stepi命令,它们大体与next/step相同,分别表示步过与步入,不同之处在于前者针对单条汇编指令。上述示例中连续使用ni(nexti)命令,从指令地址(rip寄存器值)可以比较容易的发现死循环,指令地址始终徘徊在0x00000000004005a8-0x00000000004005c8。

这一招数对于后台daemon程序相当有效。我曾经维护过一个带有守护进程的deamon程序,对于出现问题的运行中子进程,守护进程会将其杀死重启,但并不会记录详细原因。一日,某版本频繁重启,领导下了死命令:必须在XXX之前解决!于是动用重量级上古神器gdb挂上守护进程,让运行中子进程自生自灭。。。天可怜见,终于在一周后重现了问题,并使用上述方法确认了死循环问题及其位置。。。

那晚我梦见了花团锦簇。。。

© 著作权归作者所有

共有 人打赏支持
a
粉丝 2
博文 6
码字总数 2777
作品 0
海淀
程序员
Emscripten教程之如何调试代码(六)

翻译:云荒杯倾 本文是Emscripten-WebAssembly专栏系列文章之一,更多文章请查看专栏。 也可以去作者的博客阅读文章。 调试Emscripten代码的主要优点之一是,源代码既可以在本地平台上进行调...

云荒杯倾
2017/09/19
0
0
Linux 下段错误产生的原因

用C写了一个小程序,运行时前面部分正常,之后出现段错误提示,网上查了一下资料,明白了原因。 产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其...

曾赛
2009/11/21
0
0
Emscripten教程之代码可移植性与限制(一)

Emscripten教程之代码可移植性与限制(一) 翻译:云荒杯倾 本文是Emscripten-WebAssembly专栏系列文章之一,更多文章请查看专栏。 也可以去作者的博客阅读文章。 Emscripten代码移植主题涵盖...

云荒杯倾
2017/09/17
0
0
Android中为什么主线程不会因为Looper.loop()里的死循环卡死?

在知乎上的问题,觉得很好,就转载过来记录一下。 Android程序的运行入口是android.app.ActivityThread类的main()方法。(android-23) 而根据Looper.loop()源码可知里面是一个死循环在遍历消息...

xingjm8511
2016/06/12
114
0
关于 for 循环和 while 循环?

下列关于for循环和while循环的说法中哪个是正确的(  ) A while循环能实现的操作,for循环也都能实现 B while循环判断条件一般是程序结果,for循环判断条件一般是非程序结果 C 两种循环任何...

举个_栗子
2017/12/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

70.shell的函数 数组 告警系统需求分析

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析 20.16/20.17 shell中的函数: ~1. 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段...

王鑫linux
今天
2
0
分布式框架spring-session实现session一致性使用问题

前言:项目中使用到spring-session来缓存用户信息,保证服务之间session一致性,但是获取session信息为什么不能再服务层获取? 一、spring-session实现session一致性方式 用户每一次请求都会...

WALK_MAN
今天
6
0
C++ yield()与sleep_for()

C++11 标准库提供了yield()和sleep_for()两个方法。 (1)std::this_thread::yield(): 线程调用该方法时,主动让出CPU,并且不参与CPU的本次调度,从而让其他线程有机会运行。在后续的调度周...

yepanl
今天
4
0
Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情。并发课题对于Java来说是一个又重要又难的一大块,除非气定神闲、精力满满,否则我本身是不敢随便写...

心中的理想乡
今天
42
0
shell学习之获取用户的输入命令read

在运行脚本的时候,命令行参数是可以传入参数,还有就是在脚本运行过程中需要用户输入参数,比如你想要在脚本运行时问个问题,并等待运行脚本的人来回答。bash shell为此提 供了read命令。 ...

woshixin
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部