Linux笔记--gcc与gdb总结

关于gcc:

1.编译过程
编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。

  • 预处理
    gcc -E hello.c -o hello.i 或 gcc -E hello.c

这里写图片描述
生成文件(部分):
这里写图片描述
gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将stdio.h 文件中的内容插入到hello.c中了。

  • 编译为汇编代码(Compilation)
    预处理之后,可直接对生成的hello.i文件编译,生成汇编代码:
  gcc -S hello.i -o hello.s

这里写图片描述
gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。

  • 汇编(Assembly)
    对于上一小节中生成的汇编代码文件hello.s
  gcc -c hello.s -o hello.o

这里写图片描述
这是因为生成的是二进制文件

  • 连接(Linking)
    对于上一小节中生成的hello.o,将其与C标准输入输出库进行连接,最终生成程序hello
  gcc hello.o -o hello

在命令行窗口中,执行./hello, 让它说HelloWorld吧!

2.多个程序文件的编译
通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用gcc能够很好地管理这些编译单元。假设有一个由hello1.c和 hello2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序hello,可以使用下面这条命令:

gcc hello1.c hello2.c -o hello

如果同时处理的文件不止一个,gcc仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:

gcc -c hello1.c -o hello1.o
gcc -c hello2.c -o hello2.o
gcc hello1.o hello2.o -o hello

3.库文件连接
开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;Windows所使用的库文件主要放在Visual Stido的目录下的include和lib,以及系统文件夹下。但也有的时候,我们要用的库不再这些目录下,所以gcc在编译时必须用自己的办法来查找所需要的头文件和库文件。

例如我们的程序hello.c是在linux上使用c连接mysql,这个时候我们需要去mysql官网下载MySQL Connectors的C库,下载下来解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so

其中inclulde文件夹的路径是/usr/dev/mysql/include,lib文件夹是/usr/dev/mysql/lib

  • 编译成可执行文件
    首先我们要进行编译hello.c为目标文件,这个时候需要执行
  gcc –c –I /usr/dev/mysql/include hello.c –o hello.o
  • 链接
    最后我们把所有目标文件链接成可执行文件:
  gcc –L /usr/dev/mysql/lib –lmysqlclient hello.o –o hello

Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),二者的区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。

  • 强制链接时使用静态链接库
    默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。

    在/usr/dev/mysql/lib目录下有链接时所需要的库文件libmysqlclient.so和libmysqlclient.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:

  gcc –L /usr/dev/mysql/libstatic –lmysqlclient test.o –o test

静态库链接时搜索路径顺序:

  1. ld会去找GCC命令中的参数-L
  2. 再找gcc的环境变量LIBRARY_PATH
  3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

  1. 编译目标代码时指定的动态库搜索路径
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
  4. 默认的动态库搜索路径/lib
  5. 默认的动态库搜索路径/usr/lib

有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

[常用参数详解]
-c
  只激活预处理,编译,和汇编,也就是只把程序做成obj文件
  gcc -c hello.c
  将生成.o的obj文件
-S
  只激活预处理和编译,就是指把文件编译成为汇编代码。
  gcc -S hello.c
  将生成.s的汇编代码,你可以用文本编辑器察看
-E
  只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
-o
  制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感,改掉它,哈哈
-include file
  包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设定,功能就相当于在代码中使用#include
  gcc hello.c -include /root/pianopan.h 
-C
  在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的
-Ldir
  制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然编译器将只在标准库的目录找。这个dir就是目录的名称。  
-O0
-O1
-O2
-O3
  编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高   
-g
  只是编译器,在编译的时候,产生调试信息。
-static
  此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就可以运行.
-share
  此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.

对gcc的总结:
  -E :让GCC仅进行预处理后就不继续作下去了
  -S :让GCC仅进行预处理,编译后就不继续作下去了
  -c :让GCC仅进行预处理,编译,汇编后就不继续作下去了
  -o Ouput:指定输出文件,默认gcc编译输出的程序名为a.out.
  -I dir,-Idir:追加目录dir到头文件的搜索路径中
  -L dir,-Ldir:追加目录dir到库文件的搜索路径中
  -l library:指定使用的库文件,默认gcc在编译一个程序时只连接到标准c库上,是用该选项能够使他连接到指定的库上,例如若你要连接到数学库上(libm.a)则你只须指定 -lm就可以了。也就是说这个选项指定连接的库文件可以将前缀lib和后缀.a(或.so)省略。

关于gdb:
这儿有更好的
总结:
  list或l: 列出源码,每次列十行
  list加上行号:列出从改行开始的源码
  list加上函数名:列出该函数的源码
  next或n:单步执行下一条语句
  print或p:打印变量的值
  step或s:单步执行下一条语句,有函数进入执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值