gcc编译学习

以下操作都是在x86平台的linux上运行
使用 strip xx,可对可执行文件xx减小文件的尺寸而不影响运行
但不能对目标文件和共享库使用该命令。
gcc main.c -g 生成二进制的目标文件
gcc -S main.c生成汇编代码main.s
(gdb) disassemble 反编汇当前函数;再用(gdb)si逐步调试

gcc -v main.c -o main 可以查看详细的编译过程 (ubuntu下)
真正的C编译器是 /usr/lib/gcc/i486-linux-gnu/4.4.3/cc1
main.c被cc1编译成汇编程序/tmp/ccabh8rg.s。
汇编程序被as汇编成目标文件/tmp/ccEFDQim.o
目标文件连同下面的目标文件一起链接成执行文件main
/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crt1.o
/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crti.o
/usr/lib/gcc/i486-linux-gnu/4.4.3/crtend.o
/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crtn.o
usr/lib/i486-linux-gnu /tmp/ccEFDQim.o

可以用下列分析crtl.o中的符号
$ nm /usr/lib/crtl.o
$ objdump -d /usr/lib/ctrl.o

ld --verbose可以查看几个C程序的链接脚本


可由gcc -c main.c -Wall查看编译是否存在问题
隐式声明只能假定返回值都是int型


若main.c stack.c stack.h在同一目录下,gcc -c main.c编译,gcc会自动在main.c所在的目录中找到stack.h
若main.c,而stack.c和stack.h在该目录下stack下,gcc -c main.c -Istack,-I表示gcc会在stack子目录中寻找头文件
或者在main.c中修改#include "stack/stack.h"
gcc -E 可以查看预处理的结果

# ar rs libstack.a stack.o push.o pop.o is_empty.o
ar: creating libstack.a
打包成一个静态库libstack.a
ar把目标文件打包成静态库的格式
上述命令等价于:# ar r libstack.a stack.o push.o pop.o is_empty.o
                # ranlib libstack.a

把libstack.a和main.c编译连接在一起:
# gcc main.c -L. -lstack -Istack -o main
-L表示编译器在哪里找需要的库文件,-L.表示在当前目录找

#gcc -print-search-dirs 查看编译器默认寻找哪些目录

使用静态库,链接器只取出需要的目标文件做链接。


组成共享库的目标文件和一般的目标文件不同,在编译时要加-fPIC选项
# gcc -c -g -fPIC stack/stack.c stack/push.c stack/pop.c stack/is_empty.c
生成共享库
# gcc -shared -o libstack.so stack.o push.o pop.o is_empty.o
把main.c和共享库编译链接在一起
# gcc main.c -g -L. -lstack -Istack -o main
# ./main
./main: error while loading shared libraries: libstack.so: cannot open shared object file: No such file or directory
找不到共享库,需要设置环境变量
# ldd main
 linux-gate.so.1 =>  (0xb7762000)
 libstack.so => not found
 libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75ab000)
 /lib/ld-linux.so.2 (0xb7763000)
方法1:
在运行程序时设置环境变量LD_LIBRARY_PATH把共享库添加到搜索路径,但此方法只适合在开发调试中临时用一下,所以不推荐此方法
# export LD_LIBRARY_PATH=/home/blake/program/
#./main

方法2:
把libstack.so所在目录的绝对路径(/home/blake/program)添加到配置文件/etc/ld.so.conf,然后运行ldconfig命令
# ldd main
 linux-gate.so.1 =>  (0xb7728000)
 libstack.so => /home/blake/program/libstack.so (0xb7723000)
 libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb756e000)
 /lib/ld-linux.so.2 (0xb7729000)
方法3:
把libstack.so复制到/usr/lib或/lib目录,这样可确保动态链接器能找到这个共享库
方法4:
在链接生成可执行文件时就把libstack.so的路径写到文件中
# gcc main.c -g -L. -lstack -Istack -o main -Wl,-rpath,/home/blake/program
# readelf -a main查看多了一条rpath记录
Dynamic section at offset 0xf18 contains 22 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libstack.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [/home/blake/program]
编译libstack可指定soname,默认的soname就是libstack.so,先重新编译libstack并指定soname
# gcc -shared -Wl,-soname,libstack.so.1 -o libstack.so.1.0 libstack.so stack.o pop.o is_empty.o
生成的库文件是libstack.so.1.0,是real name
# readelf -a libstack.so.1.0
Dynamic section at offset 0xf18 contains 21 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000e (SONAME)                     Library soname: [libstack.so.1]

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值