• gdb


    虽然我们非常不愿意承认,但软件中还是有错误存在。
    调试是程序员必修的课程,如果不懂调试,那么日后写程序的时候修正代码bug会付出大量的时间和精力。
    gdb即GNU debugger。
     
     
    gcc中提到的,gcc编译选项-g,这样生成的目标代码中就添加了调试信息。
    gcc -g –o hello hello.c
    gdb完成的大部分工作都可以用很少的命令集合完成。
     
    查看是否安装了GDB
     rpm -qa | grep gdb
     
    redhat6.3默认是不安装gdb的,如果安装从系统安装盘中找到gdb-7.2-56.el6.i686.rpm这个文件
    执行以下命令

    rpm -ivh gdb-7.2-56.el6.i686.rpm

    启动gdb
      –gdb 程序名 [corefile]
    corefile是可选的,但能增强gdb的调试能力。
    Linux默认是不生成corefile的,所以需要在.bashrc文件中添加

    ulimit -c unlimited

    一个有错的程序
    #include <stdio.h>
    void test(void)
    {
        int *I = NULL;
        *i = 2;
    }
    
    int main(void)
    {
        printf(“hello world
    ”);
        test();
        return 0;
    }
    编译这个程序

    gcc –g –o hello hello.c

    运行hello

    Segmentation fault (core dumped)

    程序崩溃

    ls

    core.3563  hello  hello.c

    我们看到除了hello文件和hello.c文件之外多了core文件
     
    启动gdb

    gdb hello core.3563

    如果你不喜欢一大堆的软件信息,可以通过-q参数关闭软件信息

    gdb -q hello core.3563

    #0  0x08048394 in test () at hello.c:5

    5               *i = 2;

    可以看到gdb通过core告诉你,程序哪条语句出现问题
     
     
    我们做的第一件事就是在gdb环境中运行这个程序

    gdb hello

    urun命令。

    Starting program: /home/test/1/hello

    hello world

    Program received signal SIGSEGV, Segmentation fault.

    0x08048394 in test () at hello.c:5

    5               *i = 2;

    gdb不但能显示出错行号,还能说明出错出现时的内存地址,这个也是潜在的有用信息。
     
     
    test函数到底出了什么问题?
    where命令,显示导致段错误的执行函数树

    #0  0x08048394 in test () at hello.c:5

    #1  0x080483be in main () at hello.c:11

    问题出在hello.c文件的第5行。
     
     
    知道函数出错行的上下文对调试程序是很有帮助的。
    list [m,n],m,n是要显示包含错误首次出现位置的起始行和结尾行。不带参数的list将显示附近的10行代码

    1       #include <stdio.h>

    2       void test(void)

    3       {

    4               int *i = NULL;

    5               *i = 2;

    6       }

    7

    8       int main(void)

    9       {

    10              printf("hello world ");

    #0  0x08048394 in test () at hello.c:5

    #1  0x080483be in main () at hello.c:11

    gdb最有用的功能之一就是它可以显示被调试程序中任何表达式、变量的值。
    print 变量,表达式。
    print ‘file’::变量,表达式,‘’是必须的,以便让gdb知道指的是一个文件名。
    print funcname::变量,表达式

    (gdb) print i

    $1 = (int *) 0x0

    显示指针变量i的值为0。
    whatis 命令可以告诉你变量的类型, ptype 告诉你结构的定义。

    (gdb) whatis i

    type = int *

     
    break命令设置断点
      –break linenum
      –break funcname
      –break filename:linenum
      –break filename:funcname
     
    退出gdb,重新进入调试模式
    gdb -q hello

    (gdb) break 4

    Breakpoint 1 at 0x804838a: file hello.c, line 4.

    (gdb) run

    Starting program: /home/test/1/hello

    hello world

    Breakpoint 1, test () at hello.c:4

    4               int *i = NULL;

    ugdb在第4行停止。
     
     
    continue命令从断点以后继续执行。
    delete删除一个断点。
    如果设置了很多断点,忘记了哪些断点已经触发,可以使用info break。

    (gdb) info break

    Num     Type           Disp Enb Address    What

    1       breakpoint     keep y   0x0804838a in test at hello.c:4

            breakpoint already hit 1 time

     
    改变一个变量的值。

    set variable varname = value

    varname是变量名称,value是变量的新值。
     
     
    单步调试
    step命令
      –当遇到一个函数的时候,step将进入函数,每次执行一条语句,相当于step into
    next命令
      –当遇到一个函数的时候,next将执行整个函数,相当于step over
    return [value]命令
      –停止执行当前函数,将value返回给调用者,相当于step return
    如果需要重复执行一条命令,不需要每次都键入命令,gdb记住了最后一个被执行的命令,只要简单的按enter键就可以重复执行最后的命令
     
  • 相关阅读:
    linux基础——虚拟机的创建及安装操作系统
    并发编程之多进程
    操作系统与进程(理论知识点)
    粘包
    socket-网络编程
    网络编程1
    网络编程
    异常
    元类
    反射与内置方法
  • 原文地址:https://www.cnblogs.com/shichuan/p/4475176.html
Copyright © 2020-2023  润新知