• Linux学习系列之Linux入门(三)gcc学习


      GCCGNU Compiler CollectionGNU编译器套装),是一套由GNU开发的编程语言编译器。它是一套以GPL及LGPL许可证所发布的自由软件,也是GNU计划的关键部分,亦是自由的类Unix及苹果电脑Mac OS X 操作系统的标准编译器。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。详见百度百科维基百科、gcc官网。

       一、GCC的编译过程

       二、GCC的常用操作

       三、官方参考手册的阅读

       四、主要参考资料

      GCC的编译过程主要分为四个阶段,预处理(Pre-Processing,cpp工具)、编译(Compiling,ccl工具)、汇编(Assembling,as工具)、链接(Linking,ld工具)。每一步执行,其指令为gcc [选项] 要编译的文件 [选项] [目标文件],现以hello.c程序为例为逐一介绍。

    1 #include<stdio.h>
    2 
    3 int main(void)
    4 {
    5     printf("Hello World!
    ");
    6     return 0;
    7 }

     1 预处理:

    gcc –E hello.c –o hello.i

    2 编译:

    gcc –S hello.i –o hello.s

    3 汇编:

    gcc –c hello.s –o hello.o

    4 连接:

    gcc hello.o –o hello

    5 以上各步,我们可以通过vim查看各生成文件(-o后面的文件)的内容,其实:

     hello.c : 最初的源代码文件;
     hello.i : 经过编译预处理的源代码,该步主要完成宏(#开头的代码)替换,其中选项-E控制命令的停止;
     hello.s : 汇编处理后的汇编代码,该步主要完成将上一步的生成的文件,转换成汇编代码,其中选项-S控制命令的停止;
     hello.o : 编译后的目标文件,即含有最终编译出的机器码,但它里面所引用的其他文件中函数的内存位置尚未定义。
     hello   : 最终的可执行文件,该步主要完成对目标文件的链接工作。

    二、GCC的常用操作

    (一)编译命令

       1 gcc -Wall file.c -o file

         该命令表示在将源文件file.c编译成可执行文件file,其中-Wall表示开户警告检查功能,-o(object)代表后面是目标文件;

       2 gcc -Wall file.c /xx/xx/libName.a -o file

         该命令与上面的区别在于,该源文件中使用到系统库文件(功能文件,如线程或数学函数等)或函数(一般位于/usr/lib和/usr/local/lib下),故需要显式的指明其地址;

       3 gcc -Wall file.c -lName -o file

        该命令作用同上式,差别在于,它使用选项的形式,指出系统的库,注意:libName.a和-lName间的对应关系

        4 gcc -Wall -I/xx/include -L/xx/lib file.c -o file

        该命令的作用同上式,差别在于,该源文件使用到了系统库中没有的头文件和库文件,故需要显式的指出其位置;

       注:编译器一般的搜索路径为:由-I-L指定的路径->由环境变量指定的路径(C_INCLUDE_PATH LIBRARY_PATH LD_LIBRARY_PATH)->默认的系统目录

    5 gcc -Wall -g file.c -o file

        该命令的作用同1,差别在于,其开启了调试功能;

    (二)工具应用

     1 查看文件的属性(如某一可执行文件是由动态库生成的还是静态库生成的)

      file filename

     2 查看文件的符号表(如检查某个库是否包含的特定函数的定义)

      nm filename

     3 查看文件的动态库属性(如检查可执行文件并显示它需要的共享库的列表)

      ldd filename

    4 使用性能剖析器(gprof)

    5 代码覆盖测试(gcov)

    6 归档工具(ar,创建静态库)

      1 准备Name.h文件和filenameN.c文件;

      2 将.c文件编译成对应的.o文件(gcc -c filenameN.c [-o filenameN.o])

      3 ar cr libName.a filename1.o filename2.o ... filenameN.o(cr表示Create and replace,libName为静态库的名字);

      4 ar t libName.a (可以查看该静态库中包含的“对象文件”);

    7 动态库创建

      动态库的创建主要有三种方法:ld相对来说比较复杂,而gcc -share相对简单,但是-share并非在任何平台都可以使用,而GNU提供了一个更好的工具libtool,专门用来在各种平台上生成各种库。在此,我们简单介绍一下gcc制作动态库的过程:

       1 准备Name.h文件和filenameN.c文件;

       2 将.c文件编译成对应的.o文件(gcc -c filenameN.c [-o filenameN.o])

       3 gcc -shared -fPIC -o libName.so filename1.o filename2.o ... filenameN.o()

       注:

      -shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
     -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真 正代码段共享的目的。

    8 Segmentation fault (core dumped)的分析解决

      该错误(崩溃)表示程序试图访问不在分配给它的内存区域之列的受限制的内存“段”(segmentation)。而一般只要显示了报错信息“core dumped”,操作系统就在当前目录下生成了一个名为“core”的文件。该core文件包含程序在被终结时用到的内存页面的完整备份。如果没有该core文件,那么我们通过输入ulimit -c unlimited命令,并再试编译(带上-g选项),就会得到这个文件。那么怎样进行查看该错误的出处呢?

     gdb a.out core最后一行(gdb)是 GNU 调试器的提示符----它表示现在新的命令可以被输入了。 

    要调查程序崩溃的原因,我们用调试器的 print 命令来显示指针 p 的值:

       三、官方参考手册的阅读

       四、主要参考资料

  • 相关阅读:
    我爱工程化 之 gulp 使用(二)
    我爱工程化 之 gulp 使用(一)
    用户体验之输入框设想
    SEO优化
    js代码优化
    RequireJs 依赖管理使用
    Git 安装与使用(一)
    Webstorm 配置与使用 Less
    Less使用——让老司机带你飞
    Node安装与环境配置
  • 原文地址:https://www.cnblogs.com/gjianw217/p/3446464.html
Copyright © 2020-2023  润新知