跳转至

gcc_g++_gdb

2、简述GDB常见的调试命令,什么是条件断点,多进程下如何调试。

GDB调试:gdb调试的是可执行文件,在gcc编译时加入 -g ,告诉gcc在编译时加入调试信息,这样gdb 才能调试这个被编译的文件 gcc -g tesst.c -o test GDB命令格式

  1. quit:退出gdb,结束调试
  2. list:查看程序源代码 list 5,10:显示5到10行的代码 list test.c:5, 10: 显示源文件5到10行的代码,在调试多个文件时使用 list get_sum: 显示get_sum函数周围的代码 list test.c get_sum: 显示源文件get_sum函数周围的代码,在调试多个文件时使用
  3. reverse-search:字符串用来从当前行向前查找第一个匹配的字符串
  4. run:程序开始执行
  5. help list/all:查看帮助信息
  6. break:设置断点 break 7:在第七行设置断点 break get_sum:以函数名设置断点 break 行号或者函数名 if 条件:以条件表达式设置断点
  7. watch 条件表达式:条件表达式发生改变时程序就会停下来
  8. next:继续执行下一条语句 ,会把函数当作一条语句执行
  9. step:继续执行下一条语句,会跟踪进入函数,一次一条的执行函数内的代码
  10. continue:继续运行到下一个断点

条件断点:break if 条件 以条件表达式设置断点

多进程下如何调试:用set follow-fork-mode child 调试子进程 或者set follow-fork-mode parent 调试父进程

12、说说静态库和动态库怎么制作及如何使用,区别是什么

静态库的制作:

gcc  hello.c  -c //这样就生成hello.o目标文件
ar rcs libhello.a  hello.o//生成libhello.a静态库

静态库的使用:

gcc main.c -lhello -o staticLibrary//main.c和hello静态库链接,生成staticLibrary执行
文件
/*
    main.c:是指main主函数
    -lhello:是我们生成的.a 文件砍头去尾(lib不要 .a也不要)前面加-l
    -L:是指告诉gcc编译器先从-L指定的路径去找静态库,默认是从/usr/lib/ 或者  
/usr/local/lib/ 去找。
    ./:是指当前路径的意思
    staticLibrary:是最后想生成的文件名(这里可随意起名字)
*/

动态库的制作:

gcc -fPIC a.c b.c c.c -c
gcc -shared -o libmytest.so a.o b.o c.o

gcc -shared -fPIC hello.c -o libhello.so
-shared 指定生成动态库
-fPIC :fPIC选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。

动态库的使用:

gcc main.c -L./ -lhello  -o dynamicDepot
/*
    main.c:是指main主函数
    -lhello:是我们生成的.so 文件砍头去尾(lib不要 .so也不要)前面加-l
    -L:是指告诉gcc编译器先从-L指定的路径去找动态库,默认是从/usr/lib/ 或者 
/usr/local/lib/ 去找。
    ./:是指当前路径的意思
    dynamicDepot:是最后想生成的文件名(这里可随意起名字)
*/

区别:

  1. 静态库代码装载的速度快,执行速度略比动态库快。
  2. 动态库更加节省内存,可执行文件体积比静态库小很多。

  3. 静态库是在编译时加载,动态库是在运行时加载。

  4. 生成的静态链接库,Windows下以.lib为后缀,Linux下以.a为后缀。 生成的动态链接库,Windows下以.dll为后缀,Linux下以.so为后缀。

14、gdb调试

1.启动gdb
start -- 只执行一步,停在第一行执行语句
                n -- next
                s -- step(单步) -- 可以进入到函数体内部
                c - continue -- 直接停在断点的位置

2. 查看代码:
        l -- list,查看所在的源代码行附近的内容
        l 10(函数名)
        l filename:行号(函数名)
3. 设置断点:
        (断点需要在程序start后才能加)
        设置当前文件断点:
            b -- break
            b 10(函数名)

        设置指定文件断点:
            b fileName:行号(函数名)

        设置条件断点:
            b 10 if value==19
        删除断点:
            delete -- del - d
            d 断点的编号
                获取编号: info -- i
                                    info b
4. 查看设置的断点
5. 开始 执行gdb调试
        执行一步操作: 
            继续执行:
        执行多步, 直接停在断点处:
5. 单步调试
        进入函数体内部: s
            从函数体内部跳出: finish
        不进入函数体内部:
            n
        退出当前循环: u
6. 查看变量的值: p -- print
7. 查看变量的类型: ptype 变量名
8. 设置变量的值:  set var 变量名 = 赋值;没办法接收函数的返回值,直接p function()打印返回值
9. 设置追踪变量
        display
        取消追踪变量
        undisplay 编号
                获取编号: info display
10. 退出gdb调试
            quit
使用场景
    程序编译无误,但是有逻辑错误
    使用文字终端(shell),实现一个单步调试的功能
    生成可执行文件之前必须加参数 -g
        gcc hello.c -o hello -g
启动gdb调试
    gdb + 可执行文件 (如:gdb hello)
gdb相关命令
    l(list) --> 列出文件的代码清单
        l + 行号(l 32) --> 代码从第32行开始显示

    b(break)--> 设置断点
        b + 行号(b 12)--> 在第12行设置断点
        b + 行号(2) + 条件(if i=5) --> 在第2行设置断点,只有i等于5时生效

    info b(break)--> 查看断点信息

    info source --> 查看当前源代码文件的路径  info sources查看全部源代码

    r(run)--> 启动或重新启动程序,可加参数,会停在第一个断点处

    start --> 单步执行,运行程序,停在第一行执行语句

    disable/enable + 断点号 --> 设置断点是否有效

    d(delete)+ 断点号 --> 删除指定断点号对应的断点

    p(print) + 变量名 --> 打印变量值

    display + 变量名 --> 追踪变量
        之后每执行一步,该变量值都会被打印出来

    undisplay + 变量名编号 --> 取消跟踪

    n(next)--> 下一行(不会进入到函数体内部)

    s(step)--> 下一步(会进入到函数体内部)

    ptyte + 变量名 --> 查看变量的类型

    (fin)finish --> 结束当前函数,返回到函数调用点

    set --> 设置变量的值 set var n=100

    q(quit) --> 退出gdb