zoukankan      html  css  js  c++  java
  • GDB 调试多线程多进程

    GDB是linux下的调试利器,在c/c++程序开发过程中必不可少的。这里总结一下多进程和多线程的调试方法和技巧。

    多进程的调试:

    如下示例

    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>  
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    static int glob = 23;
    
    void test()
    {
        int i = 0;
        printf("child pid: %d
    ", getpid());
        while(1)
        {
            i++;
            sleep(3);
         printf("child running "); } }
    int main() { int pid = fork(); if(pid == 0) { test(); } else if(pid > 0){ printf("father pid : %d ", getpid()); int n = 0; while(1) { n++; sleep(4);
           printf("father running "); } } wait(pid);
    return 0; }

    编译 gcc -g process.c -o process   -g一定要加上,否则没有调试信息。

    1. 如果我想要锁定子进程/父进程该怎样?

    这里在fork之后就会产生子进程, 如果我们要锁定子进程或者父进程可以使用  set follow-fork-mode [parent|child] 来完成。

    (gdb) set follow-fork-mode child
    (gdb) b 23
    Note: breakpoint 1 also set at pc 0x4006e4.
    Breakpoint 2 at 0x4006e4: file process.c, line 23.
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x00000000004006e4 in main 
                                                       at process.c:23 inf 2, 1
        breakpoint already hit 1 time
    2       breakpoint     keep y   0x00000000004006e4 in main 
                                                       at process.c:23 inf 2, 1
    (gdb) delete breakpoints 2
    (gdb) r
    Starting program: /home/cps/桌面/IPC/process 
    
    Breakpoint 1, main () at process.c:23
    23        int pid = fork();
    (gdb) n
    [New process 37322]
    father pid : 37321
    [Switching to process 37322]
    24        if(pid == 0)
    (gdb) sparent running
    
    26            test();
    (gdb) parent running

    这里可以看到父进程一直在running, 跟踪子进程并没有停止父进程。 如果想要让父进程处于等待状态可以设置 set detach-on-fork [on | off]

    (gdb) set follow-fork-mode child 
    (gdb) b 23
    Breakpoint 1 at 0x4006e4: file process.c, line 23.
    (gdb) set detach-on-fork off
    (gdb) r
    Starting program: /home/cps/桌面/IPC/process 
    
    Breakpoint 1, main () at process.c:23
    23        int pid = fork();
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
    (gdb) n
    [New process 37548]
    child pid: 37548
    child running
    child running
    child running
    child running

    可以看到父进程并没有执行,而是暂停状态。 只有子进程处于运行状态。

    2. 如何跟踪一个正在运行的进程?

    这里就要说到attach一个进程, 可以使用gdb -p pid execfilepath 来跟踪一个进程。

    [cps@cps IPC]$ gdb -p 37682 process
    GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
    (gdb) bt
    #0  0x00007fb8d8fad650 in __nanosleep_nocancel () from /lib64/libc.so.6
    #1  0x00007fb8d8fad504 in sleep () from /lib64/libc.so.6
    #2  0x00000000004006d0 in test () at process.c:16
    #3  0x00000000004006fc in main () at process.c:26
    (gdb) print i
    No symbol "i" in current context.
    (gdb) frame 2
    #2  0x00000000004006d0 in test () at process.c:16
    16            sleep(3);
    (gdb) print i
    $1 = 8
    (gdb) 

    这里的第一个print i 并没有打印东西,原因是没有进入堆栈, 我们进入test的堆栈后就可以查看变量。同时在gdb中也可以attach到一个进程中attach pid。

    3. 进程异常crash 怎样查看?

    这种情况下要打开coredump, 使用命令ulimit -c 1024 设置coredump开启。最后将dump文件和可执行文件 一同加载到gdb。 gdb coredump execfile。 进入gdb后 执行bt 和where 查看出错的地方。但是一般情况下的段错误用这种方法可很难查到。一般做法就是一步一步的调试,这种情况一般都是非法访问内存造成的,在最有可能出错的地方打断点。这种情况并没有较为直接的方法。

    多线程调试:

    1. 查看当前进程中的所有线程

    info threads  查看当前进程下的所有线程。前面有*代表当前处于的线程。

    thread id  可以切换当前处于的线程,bt查看线程的堆栈

    2. 锁定一个线程

    当我们在调试程序时, 若是想要调试某个线程,程序在执行过程中容易在线程之间来回切换, 我们可以选择一个线程后可以锁定它。

    thread id 选定这个线程

    set scheduler-locking on 可以用来锁定这个线程 只观察这个线程的运行情况。 当锁定这个线程时, 其他线程就处于了暂停状态。

    3. 锁定一个线程,让其他线程照常执行

    锁定一个线程让其他线程照常运行,这种用法在gdb 7.0以上的版本是支持的。可以如下设置gdb

    set target-async 1
    set pagination off
    set non-stop on

    这里的几个命令要在程序运行之前运行这些。

    多进程和多线程的调试技巧还有很多, 这里只是说了一些常见的基本用法。 至于其他的一些gdb用法可以查看gdb help。

  • 相关阅读:
    【CSS】419- 彻底搞懂word-break、word-wrap、white-space
    【Webpack】418- 深度优化 Webpack 性能,翻倍构建性能
    【React】417- React中componentWillReceiveProps的替代升级方案
    巩固java(二)----JVM堆内存结构及垃圾回收机制
    巩固java(一)----java与对象
    Latex 公式换行问题,(换行,等号对齐)
    Android FoldingLayout 折叠布局 原理及实现(二)
    19.最省钱的app发短信方法
    Android FoldingLayout 折叠布局 原理及实现(一)
    18.app后端如何实现LBS
  • 原文地址:https://www.cnblogs.com/MaAce/p/8467182.html
Copyright © 2011-2022 走看看