错题集
May God Bless You

开发环境:

  CentoOs(Linux )

 

起因:

  最近在项目开发过程中需要生成.so文件来给其他的程序调用,而我的这部分程序又需要调用其他的.so,这对于一个刚刚入职的程序猿来说着实有些令人着急,大致的项目需要如图,其中libStd.so是项目的标准库,和我的.so在同一父目录下,libmkl_xxx.so是mkl库,在系统目录下。

当时由于是第一次生成.so(年少无知),照着网上的代码直接就编译了,然后其他同事在使用时出现undefined symbol <something>.

错误代码:

  

g++ -c -g -fPIC Dir1/*.cpp Dir2/*.cpp -I/opt/intel/mkl/include

g++ -shared -o libMyLib.so *.o

 概念:

  函数库可以分成动态库(dynamic)和静态库(static),静态库相当于把你的所有文件都打了包,以后要跟其他程序集成的话就得把整个包给集成进去,这往往导致最终程序会变得很大,而且也不易升级、维护,动态库相当于一个开放的包,大家都可以用,只要你链接到它,你也可以用,我链接到之后我也可以用,是公共、独立的。两者更进一步的区别参考链接【1】在不同系统上这两者命名稍微有些不同:

(后缀) Windows Linux
静态库 .lib .a
动态库 .dll .so

 

  .so文件是shared object文件,即共享对象,也就是说其在加载后是可以被多个进程所共享,至于如何实现可以参考链接【2】。

  -fPIC: Position Independent Code,参见链接【2】

  -shared:表示产生的是共享对象

  由于在链接产生共享对象的时候需要检查语法和语义,所以在链接阶段需要指定链接的库名-l和库所在位置-L【1】(这也是我出现上面的错误的原因)

解决方案:

  

g++ -c -g -fPIC Dir1/*.cpp Dir2/*.cpp -I/opt/intel/mkl/include

g++ -shared -o libMyLib.so *.o -lStd -L../PATH_A/TO/Bin -lmkl_xxx -L/PATH_B/TO_MKL_XXX

 后续:

  为了查看自己生成的库链接对不对,可以使用

ldd MyLib

  这条指令用于查看依赖项,即你的库有没有链接成功

  可以看到上面的libBarbeque.so没有找到,这是为什么的?我明明在链接阶段指定了对应的.so才对?先别急,这是因为你虽然刚刚指定库,但是系统在查找时默认只会在当前路径或者系统指定的LD_LIBRARY_PATH目录下查找,所以你只需要把依赖的.so放到当前目录下,或者用配置环境变量的方式使系统知道你需要在哪里找,可以参考链接【3】(记得是修改LD_LIBRARY_PATH不是默认的PATH!)

  最后注意,在实际运行的时候也需要指定对应的库和路径,在LD_LIBRARY_PATH中添加.so所在文件夹,这样可以确保程序顺利调用

【1】http://blog.csdn.net/nieyinyin/article/details/6890557:linux中的.so和.a文件

【2】http://www.cnblogs.com/cswuyg/p/3830703.html:linux共享对象之编译参数fPIC

    简要提纲(仅供自己观看,有理解不对的请谅解!)

     1.如果不采用PIC,相当于给每个进程开专线,这样物理内存利用率不高;PIC在我认为就是建立了一个中转站,大家先来中转站,再转到对应的模块;

【3】http://www.cnblogs.com/hust-chenming/p/4943268.html:linux查看和修改PATH环境变量的方法

posted on 2017-09-15 14:17  野蛮小卒  阅读(8482)  评论(0编辑  收藏  举报