zoukankan      html  css  js  c++  java
  • gdb调试多线程程序总结

    gdb调试多线程程序总结

     来源 https://www.cnblogs.com/jingzhishen/p/4324071.html

    一、多线程调试
    1. 多线程调试,最重要的几个命令:
    info threads                        查看当前进程的线程。
                                              GDB会为每个线程分配一个ID, 后面操作线程的时候会用到这个ID.
                                              前面有*的是当前调试的线程.
    thread <ID>                      切换调试的线程为指定ID的线程。
    break file.c:100 thread all    在file.c文件第100行处为所有经过这里的线程设置断点。
    set scheduler-locking off|on|step    
          在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,
          怎么只让被调试程序执行呢?
          通过这个命令就可以实现这个需求。
             off      不锁定任何线程,也就是所有线程都执行,这是默认值。
             on       只有当前被调试程序会执行。
             step     在单步的时候,除了next过一个函数的情况
                      (熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,
                      只有当前线程会执行。
    thread apply ID1 ID2 command        让一个或者多个线程执行GDB命令command
    thread apply all command            让所有被调试线程执行GDB命令command。

    2. 使用示例:
    线程产生通知:在产生新的线程时, gdb会给出提示信息
    (gdb) r
    Starting program: /root/thread 
    [New Thread 1073951360 (LWP 12900)] 
    [New Thread 1082342592 (LWP 12907)]---以下三个为新产生的线程
    [New Thread 1090731072 (LWP 12908)]
    [New Thread 1099119552 (LWP 12909)]

    查看线程:使用info threads可以查看运行的线程。
    (gdb) info threads
      4 Thread 1099119552 (LWP 12940)   0xffffe002 in ?? ()
      3 Thread 1090731072 (LWP 12939)   0xffffe002 in ?? ()
      2 Thread 1082342592 (LWP 12938)   0xffffe002 in ?? ()
    * 1 Thread 1073951360 (LWP 12931)   main (argc=1, argv=0xbfffda04) at thread.c:21
    (gdb)
    注意,行首为gdb分配的线程ID号,对线程进行切换时,使用该ID号码。
    另外,行首的星号标识了当前活动的线程
    切换线程:
    使用 thread THREADNUMBER 进行切换,THREADNUMBER 为上文提到的线程ID号。
    下例显示将活动线程从 1 切换至 4。
    (gdb) info threads
       4 Thread 1099119552 (LWP 12940)   0xffffe002 in ?? ()
       3 Thread 1090731072 (LWP 12939)   0xffffe002 in ?? ()
       2 Thread 1082342592 (LWP 12938)   0xffffe002 in ?? ()
    * 1 Thread 1073951360 (LWP 12931)   main (argc=1, argv=0xbfffda04) at thread.c:21
    (gdb) thread 4
    [Switching to thread 4 (Thread 1099119552 (LWP 12940))]#0   0xffffe002 in ?? ()
    (gdb) info threads
    * 4 Thread 1099119552 (LWP 12940)   0xffffe002 in ?? ()
       3 Thread 1090731072 (LWP 12939)   0xffffe002 in ?? ()
       2 Thread 1082342592 (LWP 12938)   0xffffe002 in ?? ()
       1 Thread 1073951360 (LWP 12931)   main (argc=1, argv=0xbfffda04) at thread.c:21
    (gdb)
    以上即为使用gdb提供的对多线程进行调试的一些基本命令。
    另外,gdb也提供对线程的断点设置以及对指定或所有线程发布命令的命令

    二、调试宏
    在GDB下, 我们无法print宏定义,因为宏是预编译的。
    但是我们还是有办法来调试宏,这个需要GCC的配合。
    在GCC编译程序的时候,加上
      -ggdb3   参数,这样,你就可以调试宏了。

    另外,你可以使用下述的GDB的宏调试命令 来查看相关的宏。
    info macro   查看这个宏在哪些文件里被引用了,以及宏定义是什么样的。
    macro         查看宏展开的样子。

    三、源文件
    GDB时,提示找不到源文件。
    需要做下面的检查:
    编译程序员是否加上了 -g参数 以包含debug信息。
    路径是否设置正确了。
    使用GDB的directory命令来设置源文件的目录。

    下面给一个调试/bin/ls的示例(ubuntu下)
    $ apt-get source coreutils
    $ sudo apt-get install coreutils-dbgsym
    $ gdb /bin/ls
    GNU gdb (GDB) 7.1-ubuntu
    (gdb) list main
    1192    ls.c: No such file or directory.
    in ls.c
    (gdb) directory ~/src/coreutils-7.4/src/
    Source directories searched: /home/hchen/src/coreutils-7.4:$cdir:$cwd
    (gdb) list main
    1192        }
    1193    }
    1194
    1195    int
    1196    main (int argc, char **argv)
    1197    {
    1198      int i;
    1199      struct pending *thispend;
    1200      int n_files;
    1201

    四、条件断点
    条件断点是语法是:
      break  [where] if [condition]
    这种断点真是非常管用。
    尤其是在一个循环或递归中,或是要监视某个变量。
    注意,这个设置是在GDB中的,只不过每经过那个断点时GDB会帮你检查一下条件是否满足。

    五、命令行参数
    有时候,我们需要调试的程序需要有命令行参数, 有三种方法:
    gdb命令行的 -args 参数
    gdb环境中   set args命令。
    gdb环境中   run 参数

    六、gdb的变量
    有时候,在调试程序时,我们不单单只是查看运行时的变量,
    我们还可以直接设置程序中的变量,以模拟一些很难在测试中出现的情况,比较一些出错,
    或是switch的分支语句。使用set命令可以修改程序中的变量。
    另外,你知道gdb中也可以有变量吗?
    就像shell一样,gdb中的变量以$开头,比如你想打印一个数组中的个个元素,你可以这样:
    (gdb) set $i = 0
    (gdb) p a[$i++]
    ...  #然后就一路回车下去了
    当然,这里只是给一个示例,表示程序的变量和gdb的变量是可以交互的。

    七、x命令
    也许,你很喜欢用p命令。
    所以,当你不知道变量名的时候,你可能会手足无措,因为p命令总是需要一个变量名的。
    x命令是用来查看内存的,在gdb中 “help x” 你可以查看其帮助。
    x/x 以十六进制输出
    x/d 以十进制输出
    x/c 以单字符输出
    x/i  反汇编 – 通常,我们会使用 x/10i $ip-20 来查看当前的汇编($ip是指令寄存器)
    x/s 以字符串输出

    八、command命令
    如何自动化调试。
    这里向大家介绍command命令,简单的理解一下,其就是把一组gdb的命令打包,有点像字处理软件的“宏”。
    下面是一个示例:
    (gdb) break func
    Breakpoint 1 at 0x3475678: file test.c, line 12.
    (gdb) command 1
    Type commands for when breakpoint 1 is hit, one per line.
    End with a line saying just "end".
    >print arg1
    >print arg2
    >print arg3
    >end
    (gdb)
    当我们的断点到达时,自动执行command中的三个命令,把func的三个参数值打出来。

    http://www.cnblogs.com/aixingfou/archive/2011/07/28/2119875.html

    http://blog.csdn.net/nancygreen/article/details/14226925

    先介绍一下GDB多线程调试的基本命令。 info threads 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程。 thread ID 切换当前调试的线程为指定ID的线程。 break thread_test.c:123 thread all在所有线程中相应的行上设置断点thread apply ID1 ID2 command 让一个或者多个线程执行GDB命令command。 thread apply all command 让所有被调试线程执行GDB命令command。 set scheduler-locking off|on|step 估计是实际使用过多线程调试的人都可以发现,在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试 程序执行呢?通过这个命令就可以实现这个需求。off 不锁定任何线程,也就是所有线程都执行,这是默认值。 on 只有当前被调试程序会执行。 step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。

    gdb对于多线程程序的调试有如下的支持:

    • 线程产生通知:在产生新的线程时, gdb会给出提示信息

    (gdb) r
    Starting program: /root/thread 
    [New Thread 1073951360 (LWP 12900)] 
    [New Thread 1082342592 (LWP 12907)]---以下三个为新产生的线程
    [New Thread 1090731072 (LWP 12908)]
    [New Thread 1099119552 (LWP 12909)]

    • 查看线程:使用可以查看运行的线程。info threads

    (gdb) info threads
      4 Thread 1099119552 (LWP 12940)   0xffffe002 in ?? ()
      3 Thread 1090731072 (LWP 12939)   0xffffe002 in ?? ()
      2 Thread 1082342592 (LWP 12938)   0xffffe002 in ?? ()
    * 1 Thread 1073951360 (LWP 12931)   main (argc=1, argv=0xbfffda04) at thread.c:21
    (gdb)

    注意,行首的蓝色文字为gdb分配的线程号,对线程进行切换时,使用该该号码,而不是上文标出的绿色数字。

    另外,行首的红色星号标识了当前活动的线程

    • 切换线程:使用 thread THREADNUMBER 进行切换,THREADNUMBER 为上文提到的线程号。下例显示将活动线程从 1 切换至 4。

    (gdb) info threads
       4 Thread 1099119552 (LWP 12940)   0xffffe002 in ?? ()
       3 Thread 1090731072 (LWP 12939)   0xffffe002 in ?? ()
       2 Thread 1082342592 (LWP 12938)   0xffffe002 in ?? ()
    * 1 Thread 1073951360 (LWP 12931)   main (argc=1, argv=0xbfffda04) at thread.c:21
    (gdb) thread 4
    [Switching to thread 4 (Thread 1099119552 (LWP 12940))]#0   0xffffe002 in ?? ()
    (gdb) info threads
    * 4 Thread 1099119552 (LWP 12940)   0xffffe002 in ?? ()
       3 Thread 1090731072 (LWP 12939)   0xffffe002 in ?? ()
       2 Thread 1082342592 (LWP 12938)   0xffffe002 in ?? ()
       1 Thread 1073951360 (LWP 12931)   main (argc=1, argv=0xbfffda04) at thread.c:21
    (gdb)

          以上即为使用gdb提供的对多线程进行调试的一些基本命令。另外,gdb也提供对线程的断点设置以及对指定或所有线程发布命令的命令。

          初次接触gdb下多线程的调试,往往会忽视gdb中活动线程的概念。一般来讲,在使用gdb调试的时候,只有一个线程为活动线程,如果希望得到其他的线程的输出结果,必须使用thread命令切换至指定的线程,才能对该线程进行调试或观察输出结果。

    最后介绍一下我最近遇见的一个多线程调试和解决。

    基本问题是在一个Linux环境中,调试多线程程序不正常,info threads看不到多线程的信息。 
    我先用命令maintenance print target-stack看了一下target的装载情况,发现target"multi-thread"没有被装载,用GDB对GDB进行调试,发现在 函数check_for_thread_db在调用libthread_db中的函数td_ta_new的时候,返回了TD_NOLIBTHREAD,所 以没有装载target"multi-thread"。 
    在时候我就怀疑是不是libpthread有问题,于是检查了一下发现了问题,这个环境中的libpthread是被strip过的,我想可能 就是以为这个影响了td_ta_new对libpthread符号信息的获取。当我换了一个没有strip过的libpthread的时候,问题果然解决 了。 
    最终我的解决办法是拷贝了一个.debug版本的libpthread到lib目录中,问题解决了。 
    多线程如果dump,多为段错误,一般都涉及内存非法读写。可以这样处理,使用下面的命令打开系统开关,让其可以在死掉的时候生成core文件。 
    ulimit -c unlimited
    这样的话死掉的时候就可以在当前目录看到core.pid(pid为进程号)的文件。接着使用gdb:
    gdb ./bin ./core.pid 
    进去后,使用bt查看死掉时栈的情况,在使用frame命令。

    还有就是里面某个线程停住,也没死,这种情况一般就是死锁或者涉及消息接受的超时问题(听人说的,没有遇到过)。遇到这种情况,可以使用:
    gcore pid (调试进程的pid号)
    手动生成core文件,在使用pstack(linux下好像不好使)查看堆栈的情况。如果都看不出来,就仔细查看代码,看看是不是在if,return,break,continue这种语句操作是忘记解锁,还有嵌套锁的问题,都需要分析清楚了。

    原文地址 http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=program&Number=692404&page=0&view=collapsed

    一个 Linux 上分析死锁的简单方法

    pstack 在 Linux 平台上的简单介绍

    pstack 是 Linux(比如 Red Hat Linux 系统、Ubuntu Linux 系统等)下一个很有用的工具,它的功能是打印输出此进程的堆栈信息。可以输出所有线程的调用关系栈。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    yingc@yingc:~/tmp/sisuo$ sudo gdb -q ./lock 13011
    Reading symbols from ./lock...done.
    Attaching to program: /home/yingc/tmp/sisuo/lock, process 13011
    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 13015]
    [New LWP 13014]
    [New LWP 13013]
    [New LWP 13012]
    [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.0
    Reading 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.6
    Reading 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.2
    0xb778bc7c in __kernel_vsyscall ()
    (gdb) info threads
      Id   Target Id         Frame
      5    Thread 0xb759db40 (LWP 13012) "lock" 0xb778bc7c in __kernel_vsyscall ()
      4    Thread 0xb6d9cb40 (LWP 13013) "lock" 0xb778bc7c in __kernel_vsyscall ()
      3    Thread 0xb659bb40 (LWP 13014) "lock" 0xb778bc7c in __kernel_vsyscall ()
      2    Thread 0xb5d9ab40 (LWP 13015) "lock" 0xb778bc7c in __kernel_vsyscall ()
    * 1    Thread 0xb759e700 (LWP 13011) "lock" 0xb778bc7c in __kernel_vsyscall ()
    (gdb) t 5
    [Switching to thread 5 (Thread 0xb759db40 (LWP 13012))]
    #0  0xb778bc7c in __kernel_vsyscall ()
    (gdb) bt
    #0  0xb778bc7c in __kernel_vsyscall ()
    #1  0xb775b792 in __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/lowlevellock.S:144
    #2  0xb77571e3 in _L_lock_851 () from /lib/i386-linux-gnu/libpthread.so.0
    #3  0xb7757020 in __GI___pthread_mutex_lock (mutex=0x804a060 <mutex2>) at ../nptl/pthread_mutex_lock.c:79
    #4  0x08048738 in func1 () at lock.cpp:18
    #5  0x080487ee in thread1 (arg=0x0) at lock.cpp:43
    #6  0xb7754f16 in start_thread (arg=0xb759db40) at pthread_create.c:309
    #7  0xb768b9fe in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    (gdb)

    pstack在我机子上貌似不好使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    yingc@yingc:~/tmp/sisuo$ pstack 13011
    Could not attach to target 13011: Operation not permitted.
    detach: No such process
    yingc@yingc:~/tmp/sisuo$ sudo pstack 13011
    [sudo] password for yingc:
     
    13011: ./lock
    (No symbols found in )
    (No symbols found in /lib/i386-linux-gnu/libc.so.6)
    (No symbols found in /lib/ld-linux.so.2)
    0xb778bc7c: _fini + 0x2caec (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
    0x09279010: _fini + 0x123054c (b759db40, 1, b778bc6c, 15a6a100, e608f43e, 0) + ffffffe0
  • 相关阅读:
    HDU 1069 Monkey and Banana
    HDU 1029 Ignatius and the Princess IV
    HDU 1024 Max Sum Plus Plus
    Gym100923H Por Costel and the Match
    Codeforces 682C Alyona and the Tree
    Codeforces 449B Jzzhu and Cities
    Codeforces (ccpc-wannafly camp day2) L. Por Costel and the Semipalindromes
    Codeforces 598D (ccpc-wannafly camp day1) Igor In the Museum
    Codeforces 1167c(ccpc wannafly camp day1) News Distribution 并查集模板
    快乐数问题
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/8078670.html
Copyright © 2011-2022 走看看