linux下的调试工具gdb - Go语言中文社区

linux下的调试工具gdb


在说这个问题之前,我们先弄清楚两个概念:

1>什么是Debug版本

2>什么是Release版本

DebugRelease是两种编译方式,Debug通常称为调试版本,它包含调试信息,并且不做任何优化,便于程序员调试程序

Release称为发布版本,它往往进行了各种优化,使得程序在代码大小和运行速度都是最优的,以便用户很好的使用


我们都知道在linux下写的代码不能直接进行调试,必须将其变成可调试的debug版本之后才能进行调试

linux下有一个调试工具gdb:

windows下是ide调试工具


那么我们接下来就说一说一些调试命令(linux下)

1>首先是进入debug版本:

gcc -o exe *.c -g

2>如果要从主函数开始调试:

gdb main

3>显示主函数所在源代码

4>b + 行号:在哪一行加断点

5>显示断点:info b

6>运行:r


7>下一步:n(显示变量)


8>s:直接进入将要被调用的函数里面运行

9>p 变量名(或者display 变量名):显示变量

10>显示变量类型

11>显示变量地址: p &变量名(数组就是p 数组名)

12>list *.c:1:从头显示(再加断点)

13>直接给函数加断点:b 函数名

14>结束:finish,跳出调试:q

15>查看线程:





16>thread 切换调试的线程为指定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。

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)
后面就是直接在你的线程函数里面设置断点,然后continue到那个断点,一般情况下多线程的时候,由于是同时运行的,最好设置 set scheduler-locking on这样的话,只调试当前线程

17>linux 下调试core 的命令,察看堆栈状态命令

配置coredump

2.1 使用调试版本

一般地,在软件开发阶段,都会使用调试版本。亦即程序使用-g来编译,另外要注意,不能用strip命令对生成的可执行文件进行精简。这一切均是为了可执行文件保留着调试信息,以方便使用gdb进行调用。

2.2 设置ulimit

为了在程序崩溃时产生coredump文件,要设置coredump大小。先进行查看:

root@latelee:~# ulimit -a
time(seconds)        unlimited
file(blocks)         unlimited
data(kb)             unlimited
stack(kb)            8192
coredump(blocks)     0
memory(kb)           unlimited
locked memory(kb)    64
process              545
nofiles              1024
vmemory(kb)          unlimited
locks                unlimited

可以看到,其中coredump一行值为0,此时无法产生coredump文件。因此要设置其文件为无限大,命令:


# ulimit -c unlimited

结果如下:

root@latelee:~# ulimit -a

time(seconds)        unlimited
file(blocks)         unlimited
data(kb)             unlimited
stack(kb)            8192
coredump(blocks)     unlimited
memory(kb)           unlimited
locked memory(kb)    64
process              545
nofiles              1024
vmemory(kb)          unlimited
locks                unlimited

另外,要程序运行的同一环境下执行。比如,不能在一个终端设置ulimit,而在另一个终端运行程序,这样不能生成coredump文件的。

为了保证coredump文件名称的唯一性,可以用下面命令设置:
# echo 'core.%e.%s.%t' > /proc/sys/kernel/core_pattern  # 设置生成的coredump文件名称

2.3 万一程序因段错误等原因崩溃,则会生成core文件。

2.4 3、有了coredump文件,就可以结合可执行文件,使用gdb进行调试了,命令形式如下:
# gdb hello core

下面使用李迟当年参考uboot源码实现的命令行解析代码为例。
首先,代码编译时必须带-g选项。

然后,在命令行中设置core文件:
[latelee@latelee creadline]$ ulimit -c unlimited

运行程序:
[latelee@latelee creadline]$ ./a.out
Hit any key to stop autoboot:  0
You abort.
NotAShell> print
in print ...
Segmentation fault (core dumped)     

(已经产生了coredump文件)


下面使用gdb调试:
[latelee@latelee creadline]$ gdb a.out core.2896

gdb打印信息如下:
GNU gdb Fedora (6.8-29.fc10)
Copyright (C) 2008 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 "i386-redhat-linux-gnu"...


warning: Can't read pathname for load map: Input/output error.
Reading symbols from /usr/lib/libstdc++.so.6...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
[New process 2896]
#0  0x0084d626 in memcpy () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.9-2.i686 libgcc-4.3.2-7.i386 libstdc++-4.3.2-7.i386
(gdb)

使用bt命令查看函数调用的栈帧(用where命令也可以):
(gdb) bt
#0  0x0084d626 in memcpy () from /lib/libc.so.6
#1  0x08048660 in ?? ()
#2  0x08049f5d in do_print (argc=1, argv=0xbf8935dc) at my_command.c:31
#3  0x08048cc2 in run_command (cmd=0x804cca0 "print") at command.c:380
#4  0x08049e93 in readline_test ()
#5  0x08049ee6 in main ()
(gdb)
 可以看到最后出现的可疑的代码函数为do_print,里面使用到了memcpy,具体是哪里,可以用frame NUM查看栈帧。比如,查看第2个栈帧:
(gdb) frame 2
#2  0x08049f5d in do_print (argc=1, argv=0xbf8935dc) at my_command.c:31
31          memcpy(p, buffer, 5);
(gdb) 

可以看到,已经输出了文件名称、行号、函数等重要信息。
至此,就可以根据信息修改代码了。

下面给出错误函数代码片段:
int do_print(int argc, char * const argv[])
{
    printf("in print ...n");
    char* p = NULL;
    char* buffer = "hello";
    memcpy(p, buffer, 5);     //  注:拷贝到空指针,错误!!!
    return 0;
}







版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/lm9140802/article/details/78595957
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 20:49:05
  • 阅读 ( 1089 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢