相关gcc参数:-l -L -shared -fPIC -static -c -o
 
原文地址:【脚本之家】http://www.jb51.net/article/34990.htm
 
 
根据链接时期的不同,库又有静态库和动态库之分,有别于静态库,动态库的链接是在程序执行的时候被链接的
 
 

1 库的分类

根据链接时期的不同,库又有静态库和动态库之分。

静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。

有别于静态库,动态库的链接是在程序执行的时候被链接的。所以,即使程序编译完,库仍须保留在系统上,以供程序运行时调用。(TODO:链接动态库时链接阶段到底做了什么)

2 静态库和动态库的比较

链接静态库其实从某种意义上来说也是一种粘贴复制,只不过它操作的对象是目标代码而不是源码而已。因为静态库被链接后库就直接嵌入可执行文件中了,这样就带来了两个问题。

首先就是系统空间被浪费了。这是显而易见的,想象一下,如果多个程序链接了同一个库,则每一个生成的可执行文件就都会有一个库的副本,必然会浪费系统空间。

再者,人非圣贤,即使是精心调试的库,也难免会有错。一旦发现了库中有bug,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,然后重新编译。

而动态库的出现正弥补了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。

那么,是不是静态库就一无是处了呢?

答曰:非也非也。不是有句话么:存在即是合理。静态库既然没有湮没在滔滔的历史长河中,就必然有它的用武之地。想象一下这样的情况:如果你用libpcap库编了一个程序,要给被人运行,而他的系统上没有装pcap库,该怎么解决呢?最简单的办法就是编译该程序时把所有要链接的库都链接它们的静态库,这样,就可以在别人的系统上直接运行该程序了。

所谓有得必有失,正因为动态库在程序运行时被链接,故程序的运行速度和链接静态库的版本相比必然会打折扣。然而瑕不掩瑜,动态库的不足相对于它带来的好处在现今硬件下简直是微不足道的,所以链接程序在链接时一般是优先链接动态库的,除非用-static参数指定链接静态库。

动态链接库

1. 创建动态链接库

代码如下:
#include<stdio.h>
void hello()
{
  printf("hello world/n");
}

用命令gcc -shared hello.c -o libhello.so -fPIC编译为动态库。可以看到,当前目录下多了一个文件libhello.so。fPIC告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

【转载者注:so是Linux下动态链接库的后缀,ld对此后缀是敏感的,不可以改成如dll等其他后缀.又由于gcc -c在不加-o来指定文件名的情况下,不管其他参数如何,都会生成xxxxx.o文件,因此编译链接库时必须用-o指定一个名为xxxx.so的文件名。】

2. 再编辑一个测试文件test.c,内容如下

代码如下:
#include<stdio.h>
int main()
{
  printf("call hello()");
  hello();
}

编译 gcc test.c -lhello (转载者注:-lxxxxx 中间没有空格,是告诉gcc要去找libxxxxx.so这个库,而libxxxxx.so文件名是gcc去生成的,是固定格式,不可更改。)
-l 选项告诉编译器要使用hello这个库。奇怪的地方是动态库的名字是libhello.so,这里却使用hello.
但这样还不行,编译会出错。

In function `main':
test.c:(.text+0x1d): undefined reference to `hello'
collect2: ld returned 1 exit status
这是因为hello这个库在我们自己的路径中,编译器找不到。
需要使用-L选项,告诉hello库的位置
gcc test.c -lhello -L. -o test
-L. 告诉编译器在当前目录中查找库文件

3. 编译成功后执行./test, 仍然出错

说找不到库

有两种方法:

一、可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行)。

二、把当前路径加入环境变量LD_LIBRARY_PATH中

当然,如果你觉得不会引起混乱的话,可以直接把该库拷入/lib,/usr/lib/等位置(无可避免,这样做也要有权限),这样链接器和加载器就都可以准确的找到该库了。

我们采用第二种方法:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
这样,再执行就成功了。

下面再讲讲静态链接库

仍使用刚才的hello.c和test.c。
1. gcc -c hello.c 注意这里没有使用-shared选项
2. 把目标文件归档    ar -r libhello.a hello.o
    程序 ar 配合参数 -r 创建一个新库 libhello.a 并将命令行中列出的对象文件插入。采用这种方法,如果库不存在的话,参数 -r 将创建一个新的库,而如果库存在的话,将用新的模块替换原来的模块。
3. 在程序中链接静态库
           gcc test.c -lhello -L. -static -o hello.static 
或者   gcc test.c libhello.a -L. -o hello.static

生成的hello.static就不再依赖libhello.a了

两个有用的命令

file程序是用来判断文件类型的,在file命令下,所有文件都会原形毕露的。
顺便说一个技巧。有时在 windows下用浏览器下载tar.gz或tar.bz2文件,后缀名会变成奇怪的tar.tar,到Linux有些新手就不知怎么解压了。但 Linux下的文件类型并不受文件后缀名的影响,所以我们可以先用命令file xxx.tar.tar看一下文件类型,然后用tar加适当的参数解压。

另外,还可以借助程序ldd实用程序来判断。
ldd是用来打印目标程序(由命令行参数指定)所链接的所有动态库的信息的,如果目标程序没有链接动态库,则打印“not a dynamic executable”,ldd的用法请参考manpage。

【转】GCC编译使用动态链接库的更多相关文章

  1. [转载]GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结

    来自http://blog.csdn.net/benpaobagzb/article/details/51364005 GCC 编译使用动态链接库和静态链接库 1 库的分类 根据链接时期的不同,库又有 ...

  2. GCC 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  3. GCC 编译使用动态链接库和静态链接库的方法

    1 库的分类 依据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的.所以生成的可执行文件就不受库的影响了.即使库被删除了,程序依旧能够成功执行. 有别于静态库,动态库的链接是在程 ...

  4. 【转】gcc 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  5. GCC 编译使用动态链接库 LD

    可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig 2.把当前路径加入环境变量LD_LIBRARY_PATH中3. 如果你觉得不会引 ...

  6. GCC编译过程与动态链接库和静态链接库

    1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...

  7. gcc编译动态链接库

    以下是windows环境下用gcc编译动态链接库的尝试过程. 环境准备 编译使用的MinGW,64位的官网可以找到下载地址. 项目建立及代码编写 在任意地方新建一个目录,保存这个项目,然后新建一个c源 ...

  8. GCC编译C代码

    C程序的编译过程       常用文件的后缀名: gcc编译c代码 1.gcc 常用编译选项: 2.gcc编译方法 testc.c: #include <stdio.h> int main ...

  9. gcc编译时对'xxxx'未定义的引用问题

    gcc编译时对’xxxx’未定义的引用问题 gcc编译时对’xxxx’未定义的引用问题 原因 解决办法 gcc 依赖顺序问题 在使用gcc编译的时候有时候会碰到这样的问题,编译为.o(obj) 文件没 ...

随机推荐

  1. css style与class之间的区别,cssclass

    问题描述:    网页点击[导出]按钮后,将页面table内容另存成excel文件,却发现无法保存表格样式 分析过程: 1.table表格用class,而不是style.导出时并没有导出class定义 ...

  2. ARC————自动引用计数

    一.内存管理/引用计数 1.引用计数式内存管理的方式(下面四种) 对象操作 OC方法 生成并持有对象 alloc/new/copy/mutableCopyd等方法 持有对象 retain方法 释放对象 ...

  3. winform之excel导入和导出

    引用命名空间   using Microsoft.Office.Interop.Excel;DataGridView 导出到Excel public static void SaveAs(DataGr ...

  4. C# 中解决页面刷新后字体等变大问题

    来源:http://blog.csdn.net/wcsjsdn/article/details/5109605 我们在.net开发中时常会遇到一个问题,那就是,当点击某个按钮后,调用js语句,当点击& ...

  5. mac虚拟机parallels 无法启动 "Windows 7" 虚拟机

    关机前在虚拟机上安装了个游戏有点大,第二天开机就使用不了虚拟机了: 提示:mac虚拟机parallels  无法启动 "Windows 7" 虚拟机.  释放至少 241 MB 的 ...

  6. BT9034: 仅 IE 和 Opera 支持 HTMLFrameElement 和 HTMLIFrameElement 的 document 属性

    标准参考 根据 DOM-2 中的描述,HTMLFrameElement 和 HTMLIFrameElement 都没有 'document' 属性. 关于 HTMLFrameElement 对象的详细 ...

  7. WIN7 shutdown 定时/倒计时 命令关机

    解决方案: 一.可以通过DOS命令shutdown来解决 在 Win7 中,shutdown实现自动关机的方法如下: 开始->运行->cmd 运行"shutdown -s -t ...

  8. Oracle结果集 (MSSQL存储过程写报表)

    接触SQL Server比较多,写报表是用存储过程实现. 对Oracle实现像MSSQL那样,还是有很多疑问

  9. hdu 5183 Negative and Positive (NP)

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5183 Negative and Positive (NP) Description When give ...

  10. Windows Phone性能优化建议

    使用background thread解码图片 在Windows Phone中支持的图片格式有jpg和png,微软建议使用jpg格式的图片,因为jpg格式的图片在解码速度上要比png快.那么我们怎么来 ...