zoukankan      html  css  js  c++  java
  • 第01课:调试信息与调试原理

      Linux下C/C++程序开发,即使使用Makefile、Cmake等编译工具,其最终都是调用GCC这一编译工具组的。这里说的工具组,是因为编译C程序和C++程序使用的编译工具还是有一点差别的,一般编译C程序使用GCC,编译C++程序使用G++。(下文统一使用GCC这一名词代指)。

      我使用的操作系统是Deepin。如果你机器上没有GCC和GDB,可以安装一下。

        debian系列的使用  apt-get

        redhat系列的使用  yum

      一般要调试某个程序,为了能清晰地看到调试的每一行代码、调用的堆栈信息、变量名和函数名等信息,需要调试程序含有调试符号信息。使用GCC编译程序时,如果加上-g选项即可在编译后的程序中保留调试符号信息。举个例子,以下命令将生成一个带调试信息的程序hello_server。

        gcc -g -o hello_server hello_server.c

      那么如何判断hello_server是否带有调试信息呢?我们使用GDB来调试一下这个程序,GDB会显示正确读取到改程序的调试信息,在打开的Linux Shell终端输入gdb hello_server查看显示结果即可:

    GDB加载成功以后,会显示如下信息:

          Reading symbols from hello_server...done.

    另外补充两点说明:

      -- 本课程里虽然以GCC为例,但-g选项实际上同样适用于MakeFile、Cmake等工具编译生成的Linux程序。

      -- 在实际生成调试程序时,一般不仅要加上-g选项,也建议关闭编译器的程序优化选项。编译器的程序优化选项一般有五个级别,从O0-O4,O0表示不优化,从O1-O4优化级别越来越高,O4最高。这样做的目的是为了调试的时候,符号文件显示的调试变量等能与源代码完全对应起来。举个例子,假设有以下代码:

    int func()
    {
       int a = 1;
       int b = a + 1;
       int c = a + b;
       return a + b + c;       
    }
    
    int main()
    {
         int a = func();
         printf("%d
    ",a);
    }
    

      在此代码中,由于在main()函数中调用了func()函数,而func()函数值可以在编译期间直接算出来,如果开启了优化选项,在实际调试的时候,这个函数中的局部变量a,b,c,被直接的值取而代之(即编译器计算得出的值,a直接使用1,b直接使用2,c直接使用3,不会产生通过a计算b,通过a、b计算c的指令),甚至连函数func()也可能被优化掉。如果出现这种情况,调试显示的代码和实际代码可能就会有差异了,这会给排查问题带来困难。当然,上面说的优化现象是否一定会出现,不同版本的编译器可能会有不同的行为。总之一句话,建议生成调试文件时关闭编译器优化选项。

  • 相关阅读:
    phpmyadmin的登陆配置
    修改xampp-mysql密码
    php实现获取汉字笔画数
    Java学习路线图,专为新手定制的Java学习计划建议
    高德地图Bug 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: !stayUp || CLClientIs
    BitCode
    解决 The sandbox is not sync with the Podfile.lock问题时候,如下所示
    iOS时间戳与字符串
    自定义大头针标注泡泡视图无法响应事件
    'The sandbox is not sync with the Podfile.lock'问题解决
  • 原文地址:https://www.cnblogs.com/wzqstudy/p/10234446.html
Copyright © 2011-2022 走看看