Linux-GDB基本操作

GDB

c调试

对C/C++程序的调试,需要在编译前就加上-g选项

  • c++
    • $g++ hello.cpp -g -o hello
  • c
    • gcc test.c -g -o test

GDB【C编程基础】

1、进入GDB:

-------------无参数------------
① #gdb test
② #gdb test 11127
-------------有参数------------
① #gdb test
② #gdb test 11127
只需要run的时候带上参数即可【下面有例子】

如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到
test是要调试的程序,由gcc test.c -g -o test生成

2、查看源码ls: (gdb) l

  • 作用:源码会进行行号提示。如果需要查看在其他文件中定义的函数,在l后加上函数名即可定位到这个函数的定义及查看附近的其他源码

3、运行代码run: (gdb) r

  • 作用:运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。

4、程序继续运行: (gdb) c

  • 作用:继续执行,到下一个断点处(或运行结束)

5、单步运行: (gdb) n

  • 作用:遇到函数调用时,不进入此函数体(直接调用函数运行)。

6、单步运行: (gdb) s

  • 作用:如果有函数调用,进入此函数体;与命令n不同,n是不进入调用的函数的(step 遇到用户自定义的函数,将步进到函数中去运行)

7、单步运行时,中途退出: (gdb) until

  • 作用:在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。

8、单步运行时,运行到行号时退出: (gdb) until 行号

  • 作用:在一个循环体内单步跟踪时,运行至某行,不仅仅用来跳出循环

9、单步运行时,运行到行号时退出: (gdb) finish

  • 作用:运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。

10、调用函数: (gdb) call 函数(参数) 【call gdb_test(55)】

  • 作用:调用程序中可见的函数,并传递“参数”

11、退出: (gdb) q

  • 作用:退出GDB

例子:

hello.c

#include<stdio.h>
int main(int argc,char *argv[])
{
    if(1 >= argc)
    {
        printf("usage:hello name\n");
        return 0;
    }
    printf("Hello World %s!\n",argv[1]);
    return 0 ;
}

方式一:

  • gcc hello.c -g -o hello
  • (gdb)run 这是参数
    • 输出 Hello World 这是参数!

方式二:

  • gcc hello.c -g -o hello
  • (gdb) set args 这是参数
  • (gdb) run
    • 输出 Hello World 这是参数!

调试

1、设置断点

1.1根据行号设置断点: (gdb) b 9b test.c:9

这样会在运行到源码第6行时停止,可以查看变量的值、堆栈情况等;这个行号是gdb的行号

1.2根据函数名设置断点: (gdb) b printNum

1.3根据条件设置断点: (gdb) break test.c:23 if b==0 【当在b等于0时,程序将会在第23行断住。】

1.4设置临时断点(断点只想生效一次): (gdb) tbreak test.c:l0 【在第10行设置临时断点】

1.5跳过多次设置断点(前面30次都没有问题,后面可能出错): (gdb) ignore 1 30 【1是断点号】

2、查看断点处情况(breakpoints): (gdb) info b 【查看断点号b情况,可以设置多个断点】

3、根据表达式值变化产生断点: (gdb) watch n 【在某一循环处,来观察变量n的变化情况】

4、禁用或启动断点

4.1禁用所有断点

  • (gdb) disable

4.2禁用标号为bnum的断点

  • (gdb) disable bnum

4.3启用所有断点

  • (gdb) enable

4.4启用标号为bnum的断点

  • (gdb) enable bnum

4.5启动标号为bnum的断点,并且在此之后删除该断点

  • (gdb) enable delete bnum

5、断点清除

5.1删除当前行所有断点breakpoints

  • (gdb) clear

5.2删除函数名为function处的断点

  • (gdb)clear function

5.3删除文件filename中函数function处的断点

  • (gdb)clear filename:function

5.4删除行号为lineNum处的断点

  • (gdb)clear lineNum

5.5删除文件filename中行号为lineNum处的断点

  • (gdb)clear f:lename:lineNum

5.6删除所有breakpoints,watchpoints和catchpoints

  • (gdb)delete

5.7删除断点号为bnum的断点

  • (gdb)delete bnum

6、调试已运行程序

  • 先使用ps命令找到进程id
  • 再假设获取到进程id为20829,用attach调试
    • $ ps -ef|grep 进程名
    • $ gdb
    • (gdb) attach 20829

直接调试相关id进程

  • gdb hello 20829
  • gdb hello --pid 20829【都可】

例子:

test.c

#include<stdio.h>
void printNum(int a)
{
    printf("printNum\n");
    while(a > 0)
    {
    printf("%d\n",a);
    a--;
    }
}
void printNum2(int a,int num)
{
    printf("printNum\n");
    while(a > num && a>0)
    {
        printf("%d\n",a);
        a--;
    }
}
int div(int a,int b)
{
    printf("a=%d,b=%d\n",a,b);
    int temp = a/b;
    return temp;
}
int main(int argc,char *argv[])
{
    printNum2(12,5);
    printNum(10);
    div(10,0);
    return 0;
}

变量查看

1、打印基本类型变量,数组,字符数组:(gdb) p n

  • (gdb) p a

    • 输出:$1 = 10
  • (gdb) p b

    • 输出:$2 = {1, 2, 3, 5}
  • (gdb) p c

    • 输出:$3 = “hello,shouwang”

注:多个函数或者多个文件会有同一个变量名,这个时候可以在前面加上函数名或者文件名来区分

  • (gdb) p ‘a.c’::a

    • 输出:$1 = 11
  • (gdb) p ‘main’::b

    • 输出:$2 = {1, 2, 3, 5}

2、打印指针地址

  • (gdb) p d
    • 输出:$1 = (int *) 0x602010

3、打印指针指向的内容:要打印多个值,后面跟上@并加上要打印的长度或者@后面跟上变量值

  • (gdb) *p d

    • 输出:$2 = 0
  • (gdb) *p d@10

    • 输出:$3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

4、打印链表内容

  • (gdb) *p linkNode

    • 输出:(这里显示linkNode节点内容)
  • (gdb) *p $.next

    • 输出:(这里显示linkNode节点下一个节点的内容)

5、查看前面数组的内容,将下标一个一个累加

  • (gdb) set $index=0
  • (gdb) p b[$index++]
    • 输出:$11 = 1
  • (gdb) p b[$index++]
    • 输出:$12 = 2
  • (gdb) p b[$index++]
    • 输出:$13 = 3

例子:

testGdb.c

编译:gcc testGdb -g -o testGdb.c

#include<stdio.h>
#include<stdlib.h>
#include"testGdb.h"
int main(void)
{
    int a = 10; //整型
    int b[] = {1,2,3,5};  //数组
    char c[] = "hello,shouwang";//字符数组
    /*申请内存,失败时退出*/
    int *d = (int*)malloc(a*sizeof(int));
    if(NULL == d)
    {
        printf("malloc error\n");
        return -1;
    }
    /*赋值*/
    for(int i=0; i < 10;i++)
    {
        d[i] = i;
    }
    free(d);
    d = NULL;
    float e = 8.5f;
    return 0;
}

a.c

int a=11;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值