继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

调试陷入死循环程序的方法

慕村9548890
关注TA
已关注
手记 1249
粉丝 227
获赞 989

概述

应用程序陷入死循环后,界面可能不会有任何输出,所有的业务也不通,不易定位。

陷入死循环的程序占用的cpu使用率较高,通常可以通过使用top命令看出来。

对于多线程的程序,需要耐心调试,本文给出笔者近期使用的方法。

调试步骤

测试程序

编写一个多线程进入死循环的测试程序,如下:

#include <stdio.h>#include <pthread.h>#define MAX_THREAD 4static void dead_loop(void){    while(1) {        continue;
    }
}int main(void){    int i = 0;    pthread_t ntid[MAX_THREAD];//    dead_loop();
    for (i = 0; i < 4; i++) {        if (pthread_create(&ntid[i], NULL, (void *)dead_loop, NULL) == 0) {            printf("pthread id = %u\n", ntid[i]);
        }
    }    while(1) {
        pause();
    }    return 0;
}

编译:gcc -g while_test.c -pthread

该程序运行后进入死循环,下面分析调试方法。

确定陷入死循环的程序

  • 程序运行后会打印各id号,然后无任何输出,程序陷入了死循环

  • ps确认程序仍在运行,ps也可以查看进程状态

  • ps -T 查看进程中包含的线程

-> % ps -eT | grep a.out
10703 10703 pts/0    00:00:00 a.out
10703 10704 pts/0    00:00:39 a.out
10703 10705 pts/0    00:00:40 a.out
10703 10706 pts/0    00:00:41 a.out
10703 10707 pts/0    00:00:40 a.out
  • ps -eL 查看各线程的运行时间,可以辅助确认处于死循环的线程

-> % ps -eL | grep a.out
10703 10703 pts/0    00:00:00 a.out
10703 10704 pts/0    00:01:33 a.out
10703 10705 pts/0    00:01:34 a.out
10703 10706 pts/0    00:01:31 a.out
10703 10707 pts/0    00:01:34 a.out
  • top查看进程cpu使用率

  • top -H 查看各线程的使用率

  • top界面下按1查看各个cpu的占用率

-> % top -Htop - 21:47:24 up  6:18,  3 users,  load average: 0.90, 0.64, 0.60Threads: 402 total,   5 running, 396 sleeping,   0 stopped,   1 zombie%Cpu0  :100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st%Cpu1  : 99.7 us,  0.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st%Cpu2  : 99.7 us,  0.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st%Cpu3  :100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 stKiB Mem:   1024256 total,  1002628 used,    21628 free,   101592 buffersKiB Swap:  1046524 total,     4456 used,  1042068 free.   342212 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                       10796 yao       20   0   35068    608    544 R 99.9  0.1   0:15.59 a.out                                                         10797 yao       20   0   35068    608    544 R 99.9  0.1   0:15.68 a.out                                                         10794 yao       20   0   35068    608    544 R 99.3  0.1   0:15.66 a.out                                                         10795 yao       20   0   35068    608    544 R 99.3  0.1   0:15.50 a.out

调试程序死在何处

使用gdb调试程序:

  • 使用attach pid 进入之前查看到的进程

  • 使用info threads 查看线程信息,可以看到四个线程的运行位置

  • 使用thread 序号 进入指定序号的线程,打印出运行的位置

  • 使用bt 打印栈信息,查看函数调用关系

GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1Copyright (C) 2014 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 "i686-linux-gnu".
Type "show configuration" for configuration details.For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) attach 10848Attaching to process 10848Reading symbols from /home/yao/work/util/a.out...done.
Reading symbols from /lib/i386-linux-gnu/libpthread.so.0...Reading symbols from /usr/lib/debug//lib/i386-linux-gnu/libpthread-2.19.so...done.done.
[New LWP 10852]
[New LWP 10851]
[New LWP 10850]
[New LWP 10849]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
Loaded symbols for /lib/i386-linux-gnu/libpthread.so.0Reading symbols from /lib/i386-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug//lib/i386-linux-gnu/libc-2.19.so...done.done.
Loaded symbols for /lib/i386-linux-gnu/libc.so.6Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug//lib/i386-linux-gnu/ld-2.19.so...done.done.
Loaded symbols for /lib/ld-linux.so.20xb7718cb0 in ?? ()
(gdb) info threads 
  Id   Target Id         Frame 
  5    Thread 0xb7530b40 (LWP 10849) "a.out" dead_loop () at while_test.c:10
  4    Thread 0xb6d2fb40 (LWP 10850) "a.out" dead_loop () at while_test.c:10
  3    Thread 0xb652eb40 (LWP 10851) "a.out" dead_loop () at while_test.c:10
  2    Thread 0xb5d2db40 (LWP 10852) "a.out" dead_loop () at while_test.c:10* 1    Thread 0xb7531700 (LWP 10848) "a.out" 0xb7718cb0 in ?? ()
(gdb) bt#0  0xb7718cb0 in ?? ()#1  0xb754ca83 in __libc_start_main (main=0x8048552 <main>, argc=1, argv=0xbf999c34, init=0x80485d0 <__libc_csu_init>, 
    fini=0x8048640 <__libc_csu_fini>, rtld_fini=0xb7729180 <_dl_fini>, stack_end=0xbf999c2c) at libc-start.c:287#2  0x08048471 in _start ()(gdb) thread 2[Switching to thread 2 (Thread 0xb5d2db40 (LWP 10852))]#0  dead_loop () at while_test.c:1010      }
(gdb) bt#0  dead_loop () at while_test.c:10#1  0xb76e7f70 in start_thread (arg=0xb5d2db40) at pthread_create.c:312#2  0xb761ebee in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129

结论

对于陷入死循环的程序,服务器一般会频繁地散热,在多线程业务复杂的程序中有可能出现。

开发人员在编程时需要考虑全面细致,尽量注意到可能的异常,很多死循环是因为没有预料到的异常引入的。

对于陷入死循环的程序,稳位步骤,逐步调试,并不难定位原因。



作者:guotianqing
链接:https://www.jianshu.com/p/b7e2140bc001


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP