Linux C/C++编程FAQ系列 之二

Posted by c4pr1c3 on November 18, 2010

创建和使用静态库文件(.a)

创建和使用共享链接库文件(.so)

检查可执行文件中的所有共享库文件的依赖是否可以正确的找到

查看ld的搜索路径

为何在程序出现段错误等严重内存错误时系统无法生成core dump文件?


创建和使用静态库文件(.a)

step 1: 将源代码编译成obj文件

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hash.c通过gcc先编译成.o文件。

在系统提示符下键入以下命令得到hash.o文件。

$ gcc -c hash.c -o hash.o

step 2: 由obj文件创建静态库

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为commonds,则静态库文件名就是libcommonds.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。

在系统提示符下键入以下命令将创建静态库文件libcommonds.a。

$ ar cr libcommonds.a hash.o

step 3: 在程序中使用静态库

静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。

在主调程序中,我们只需要包含静态库的头文件hash.h,然后在主程序main中直接调用hash.h中声明并且hash.c中已经实现的函数。

在系统提示符下键入以下命令将创建可执行文件

$ gcc -o main main.c -L. -lcommonds

提示:在可执行文件创建之后,之前创建的静态库文件(.a结尾的文件)已经是可有可无的了。这是因为静态库中的公用函数已经连接到目标文件(例如这里生成的可执行文件)中了。

创建和使用共享链接库文件(.so)

step 1: 将源代码编译成obj文件

在系统提示符下键入以下命令得到hash.o文件。

$ gcc -c hash.c -o hash.o

step 2: 由obj文件创建动态库

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为commonds,则动态库文件名就是libcommonds.so。用gcc来创建动态库。

$ gcc -shared -fPCI -o libcommonds.so hash.o

step 3: 在程序中使用动态库

在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。

$ gcc -o hello main.c -L. -lmyhello

说明:

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 -L.:表示要连接的库在当前目录中 -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称 LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用/sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

一旦程序被连接,要使用共享库,就必须在运行的时候能够找到共享库的位置。默认情况下只在公用库目录(/lib,/usr/lib)中查找,不会在当前目录中查找动态库文件。Linux下的可执行文件在执行的时候缺省是先搜索/lib和/usr/lib这两个目录,然后按照ld.so.conf里面的配置搜索绝对路径,Linux缺省是不会在当前目录搜索动态库的。linux的动态库搜索顺序虽然可以说成是比较严谨,但是相对来说也比较呆板,有时候会造成不便。 其实,Linux也可以支持“加载其他目录的动态库”。只要设置合适的环境变量LD_LIBRARY_PATH就可以了。

设置方法有以下三种:

1、临时修改,log out之后就失效在terminal中执行:export LD_LIBRARY_PATH=***

2、让当前帐号以后都优先加载当前目录的动态库 修改~/.bash_profile在文件末尾加上两行: LD_LIBRARY_PATH=*** 和 export LD_LIBRARY_PATH

3、让所有帐号从此都优先加载当前目录的动态库 修改/etc/profile在文件末尾加上两行: LD_LIBRARY_PATH=*** 和 export LD_LIBRARY_PATH

PS:修改/etc/ld.so.conf也可以,但只支持绝对路径,并且必须有root权限。

提示:在同一目录下,如果同时存在“相同文件名”的静态和动态库文件(如libhash.o和libhash.so如果同时存在,则libhash.so将被优先连接),ld将优先连接动态库文件。

检查可执行文件中的所有共享库文件的依赖是否可以正确的找到

$ ldd  可执行文件

查看ld的搜索路径

$ ld --verbose | grep SEARCH

SEARCH_DIR("/usr/i486-linux-gnu/lib32"); 

SEARCH_DIR("/usr/local/lib32"); SEARCH_DIR("/lib32"); 

SEARCH_DIR("/usr/lib32"); 

SEARCH_DIR("/usr/i486-linux-gnu/lib"); 

SEARCH_DIR("/usr/local/lib"); 

SEARCH_DIR("/lib"); 

SEARCH_DIR("/usr/lib");

为何在程序出现段错误等严重内存错误时系统无法生成core dump文件?

使用ulimit -c,如果返回0,则说明系统禁止生成core dump文件。设置合适大小的core dump最大值即可。如ulimit -c 1000,(maximum core file size (in 512-byte blocks))