• 【Linux网络编程】使用GDB调试程序


    Linux中有一个强大的调试工具GDB(GNU Debugger),可以调试C和C++程序。

    GDB的主要功能如下:

    1. 设置断点
    2. 显示变量的值
    3. 单步执行
    4. 运行时修改变量的值
    5. 路径跟踪,方便跟踪代码
    6. 线程切换
    7. 其他的。。。

    使用GDB的前提是,在编译程序的时候需要加入-g选项,即 gcc -g xxx.c。当设置这个选项的时候,GCC会向程序中加入“楔子”,GDB能够利用这些楔子与程序交互。

    书上的测试程序一则:

    /*文件名:ex02-gdb-01.c*/
    #include <stdio.h>
    /* 用于printf*/
    #include <stdlib.h>
    /*用于malloc*/
    
    /* 声明函数sum为static int类型 */
    static int sum(int value);
    
    /* 用于控制输入输出的结构 */
    struct inout {
    	int value;
    	int result;
    	};
    int main(int argc, char * argv[]) {
    	/*申请内存*/
    	struct inout * io = (struct inout * ) malloc(sizeof(struct inout));
    	/*判断是否成功*/
    	if (NULL == io) {
    		/*失败返回*/
    		printf("申请内存失败
    ");
    		return -1;
    	}
    	/*判断输入参数是否正确*/
    	if (argc != 2) {
    		printf("参数输入错误!
    ");
    		return -1;
    	}
    	/* 获得输入的参数 */
    	io -> value = *argv[1] - '0';
    	/* 对value进行累加求和 */
    	io -> result = sum(io -> value);
    	printf("你输入的值为:%d,计算结果为:%d
    ", io -> value, io -> result);
    	return 0;
    }
    
    /* 累加求和函数 */
    static int sum(int value) {
    	int result = 0;
    	int i = 0;
    	/* 循环计算累加值 */
    	for (i = 0; i < value; i++) result += (i + 1);
    	/*返回结果*/
    	return result;
    }
    

    输入gcc -o test gdb-01.c -g,使其加入“楔子”。下面进入调试:

    其中test是可执行文件的名字。

    GDB常用的命令( 命令(命令简写):格式及含义 ):

    file:加载(可执行)文件,使用在gdb命令后没有接文件名的时候。

    (gdb) file gdb-01.c
    "/home/tyruschin/ClionProjects/gdb_learning/gdb-01.c": not in executable format: 不可识别的文件格式
    (gdb) file test
    Load new symbol table from "test"? (y or n) y
    Reading symbols from test...done.

    set args:设置输入参数(可以在run命令中设置,如果不设置的话,run的时候默认使用前一条run命令的参数),set args 参数1 参数2 ...

    (gdb) set args 2
    (gdb) run
    Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 2
    你输入的值为:2,计算结果为:3

    show:显示变量,show args

    (gdb) set args 2 3
    (gdb) show args
    Argument list to give program being debugged when it is started is "2 3".

    list(l):表示列出文件的代码内容。list 1表示从第一行开始,默认显示10行,按下回车键可以继续打印10行;list 1,4表示显示1到4行,此时再次按下回车则继续打印下面的10行。

    break(b):设置断点,b 行号或函数名。程序运行到断点的位置会终端,等待用户的下一步操作指令。

    具体的使用(如果有多个文件共同生成一个目标执行文件的时候,要指定文件名,如 b gdb-01.c:38 ):

    1. break 行号:程序停止在设定的行之前
    2. break 函数名称:程序停止在设定的函数之前
    3. break 行数或者函数if条件:条件为真的情况下,到达指定行或函数时停止

    查看断点信息,info break

    // 没有写编号就表示全部编号了

    删除指定的某个断点:delete breakpoints 断点编号(在info break 中找到)

    禁止断点:disable b 断点编号(此时info break中的Enb列中,显示的是n而不是y)

    允许断点(禁止的反操作):enable b 断点编号 

    清除断点:clear 断点行号

    run(r):运行程序,run args,这里的args和set args中的是一致的。运行到遇到断点会暂停下来。

    (gdb) run 3
    Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 3
    
    Breakpoint 1, sum (value=3) at gdb-01.c:39
    39		int result = 0;
    

    print(p):打印变量内容,功能强大,可以打印任何有效表达式的值。

    设置断点在28行,以上是p打印变量的例子,其中io是一个结构体数组,argv是一个字符串数组,@后面的数字表示打印的个数,超过个数之后打印处的结果是随机的。。

    whatis:变量类型检测,打印数组或者变量的类型,whatis 变量名

    ptype:变量类型检测,结构的详细定义

    set:修改变量的值,set xx=val

    display:display 变量,每次在调试到暂停的时候都会显示该值。

    (gdb) run 3
    Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 3
    
    Breakpoint 8, main (argc=2, argv=0x7fffffffde18) at gdb-01.c:33
    33		printf("你输入的值为:%d,计算结果为:%d
    ", io -> value, io -> result);
    4: argc = 2
    3: *argv = 0x7fffffffe1c6 "/home/tyruschin/ClionProjects/gdb_learning/test"
    2: argv = (char **) 0x7fffffffde18
    1: argc = 2
    

    单步调试:next(n)单步跟踪,step(s)进入某个函数,finish返回调用的函数中,continue(c)表示继续执行知道遇到断点或结束。

    (gdb) run 3
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 3
    
    Breakpoint 1, main (argc=2, argv=0x7fffffffde18) at gdb-01.c:19
    19		if (NULL == io) {
    (gdb) s
    25		if (argc != 2) {
    (gdb) s
    30		io -> value = *argv[1] - '0';
    (gdb) s
    32		io -> result = sum(io -> value);
    (gdb) s
    sum (value=3) at gdb-01.c:39
    39		int result = 0;
    (gdb) s
    40		int i = 0;
    (gdb) finish
    Run till exit from #0  sum (value=3) at gdb-01.c:40
    0x0000000000400639 in main (argc=2, argv=0x7fffffffde18) at gdb-01.c:32
    32		io -> result = sum(io -> value);
    Value returned is $1 = 6
    (gdb) s
    33		printf("你输入的值为:%d,计算结果为:%d
    ", io -> value, io -> result);
    (gdb) c
    Continuing.
    你输入的值为:3,计算结果为:6
    [Inferior 1 (process 27047) exited normally]
    

     q表示退出GDB。。

    附:书上的例子:

    /*文件名:ex02-gdb-01.c*/
    #include <stdio.h>
    /* 用于printf*/
    #include <stdlib.h>
    /*用于malloc*/
    
    /* 声明函数sum为static int类型 */
    static int sum(int value);
    
    /* 用于控制输入输出的结构 */
    struct inout {
    	int value;
    	int result;
    	};
    int main(int argc, char * argv[]) {
    	/*申请内存*/
    	struct inout * io = (struct inout * ) malloc(sizeof(struct inout));
    	/*判断是否成功*/
    	if (NULL == io) {
    		/*失败返回*/
    		printf("申请内存失败
    ");
    		return -1;
    	}
    	/*判断输入参数是否正确*/
    	if (argc != 2) {
    		printf("参数输入错误!
    ");
    		return -1;
    	}
    	/* 获得输入的参数 */
    	io -> value = *argv[1] - '0';
    	/* 对value进行累加求和 */
    	io -> result = sum(io -> value);
    	printf("你输入的值为:%d,计算结果为:%d
    ", io -> value, io -> result);
    	return 0;
    }
    
    /* 累加求和函数 */
    static int sum(int value) {
    	int result = 0;
    	int i = 0;
    	/* 循环计算累加值 */
    	for (i = 0; i < value; i++) result += (i + 1);
    	/*返回结果*/
    	return result;
    }
    

      

  • 相关阅读:
    证明最大公约数Stein算法(高精度算法)
    链表常用内容和易犯错误
    斐波那契数列——各种公式证明
    用矩阵和待定系数法求数列的分析(复杂度log(n))
    盒模型(外边距)
    盒子模型(内边距)
    盒子模型(边框)
    jupyterhub
    1分钟k线图能反映什么?(转)
    python的self
  • 原文地址:https://www.cnblogs.com/tyrus/p/linux_gdb.html
Copyright © 2020-2023  润新知