精华内容
下载资源
问答
  • 静态库 动态库 导入库 delay load rebase


    静态库
    动态库
    导入库


    delay load
    rebase


    静态库:

    以lib库(obj集合)的形式提供代码重用,需要和客户程序一起编译,成为一个二进制程序体。


    动态库:

    以二进制的dll提供代码重用,无需和客户程序一起编译。客户程序依赖其导出符号表(lib)。


    dll和lib(静态库)在代码上的差别,主要是多了__declspec(dllexport)。

    模板类不能导出。



    静态链接:
    1、#pragma comment(lib, "libname.lib"). 
    2、使用additional dependencies添加libname.lib。(同时在Additional Library Directories中设置搜寻位置)。
    以上两种方式的libname.lib可以是静态库,也可以是dll的导入库。同时,使用处需要库的头文件。
    libname.lib为dll的静态库时,静态库就被引入了,可以编译了。相应被引用的函数和代码都被拷贝到exe中。
    libname.lib为dll的导入库时,由于有了符号表和地址,也可以编译了。但函数代码和数据保存在dll中,只在exe被载入时,才把dll加载到内存。
    3、是project dependencies设置依赖。相当于加lib。可以加静态库或动态库。
    4、直接把lib文件添加到调用者的工程中。(没用过,不确定效果。)


    动态链接:

    1、LoadLibrary。


    DllMain():

    这个函数不是必须的。

    不提供时,系统给提供一个默认的。(??)


    查看dll的导出符合集:

    dumpbin.exe /export dllname.dll

    查看第三方dll所依赖的dll(特别是RT库的类型):

    dumpbin.exe /import thirdparty.dll


    dll文件位置:
    dll应该放在和exe同目录中,或放在system PATH中。


    留意使用的rt库类型:

    表6-1 C/C++运行期库

    库名 描述
    LibC.lib 用于单线程应用程序的静态链接库(当创建新应用程序时,它是默认库)
    LibCD.lib 用于单线程应用程序的静态链接库的调试版
    LibCMt.lib 用于多线程应用程序的静态链接库的发行版
    LibCMtD.lib 用于多线程应用程序的静态链接库的调试版
    MSVCRt.lib 用于动态链接M S V C R t . d l l库的发行版的输入库
    MSVCRtD.lib 用于动态链接M S V C R t D . d l l的调试版的输入库。该库同时支持单线程应用程序和多线程应用程序







    展开全文
  • Linux-动态链接与静态链接对比(动态库和静态库

    千次阅读 多人点赞 2017-12-14 17:52:46
    一、库的基础概念: 在windows平台linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。...按照库的使用方式又可分为动态库和静态库,在不同平台下...

    ####一、库的基础概念:

    #####在windows平台和linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于windows和linux的本质不同,因此二者库的二进制是不兼容的。通俗的说就是把这些常用函数的目标文件打包在一起,提供相应函数的接口,便于程序员使用。在使用函数时,只需要包对应的头文件即可。按照库的使用方式又可分为动态库和静态库,在不同平台下对应后缀也有所不同。
    #####WINDOWS下:.dll 后缀为动态库,.lib 后缀为静态库;
    #####LINUX下:.so后缀为动态库,.a后缀为静态库。


    ####二、静态库与静态链接

    #####<1>静态库:
    静态库可以简单的看成一组目标文件的集合,即很多目标文件经过压缩打包后形成的文件。比如在我们日常编程中,如果需要使用printf函数,就需要包stdio.h的库文件,使用strlen时,又需要包string.h的库文件,可是如果直接把对应函数源码编译后形成的.o文件直接提供给我们,将会对我们的管理和使用上造成极大不便,于是可以使用**“ar”**压缩程序将这些目标文件压缩在一起,形成libx.a静态库文件。
    注:静态库命名格式:lib + "库名称”+ .a(后缀) 例:libadd.a就是一个叫add的静态库


    #####<2>静态链接:
    #####对于静态库,程序在编译链接时,将库的代码链接到可执行文件中,程序运行时不再需要静态库。在使用过程中只需要将库和我们的程序编译后的文件链接在一起就可形成一个可执行文件。
    注:详细关于静态库及静态链接可参考《程序员的自我修养——链接、装载与库》第四章
    #####通过一个例子来了解下如何将我们自己写的头文件和代码同时进行编译链接,最终生成可执行文件:

    /main.c/
    
    #include <stdio.h>
    #include "add.h"
    
    int main()
    {
    	int ret = add(3, 4);
    	printf("3 + 4 = %d\n",ret);
    
    	return 0;
    }
    
    /add.c/
    
    #include "add.h"
    
    int add( int x, int y)
    {	
    	return x + y;
    }
    
    
    /add.h/
    
    #pragma once
    #include <stdio.h>
    
    int add( int x, int y);
    
    /Makefile/
    
    main : main.c libadd.a
    	gcc main.c -L . -ladd -o main
    	//-L为指定路径 .为当前目录下 -l+库名字,编译器可在指定目录下自己寻找名为add的库文件
    	
    libadd.a : 
    	gcc -c add.c -o add.o
    	
    	//ar -rc将多个编译后的文件打包为一个静态库文件
    	ar -rc libadd.a add.o
    
    .PHONY:clean
    clean:
    	rm main libadd.a
    

    #####make后输出截图:
    这里写图片描述

    #####<3>缺点:
    #####1、**内存和磁盘空间浪费:静态链接方式对于计算机内存和磁盘的空间浪费十分严重。**假如一个c语言的静态库大小为1MB,系统中有100个需要使用到该库文件,采用静态链接的话,就要浪费进100M的内存,若数量再大,那浪费的也就更多。例如下图:程序1和程序2都需要用到Lib.o,采用静态链接的话,那么物理内存中就会存放两份对应此文件的拷贝。

    这里写图片描述

    #####**2、更新麻烦:**比如一个程序20个模块,每个模块只有1MB,那么每次更新任何一个模块,用户都得重新下载20M的程序。


    ####三、动态库与动态链接

    #####**<1>动态库:**程序在运行时才去链接动态库的代码,多个程序共享库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
    注:动态库命名格式:lib + "库名称”+ .so(后缀) 例:libadd.so就是一个叫add的动态库


    #####**<2>动态链接:**由于静态链接具有浪费内存和模块更新困难等问题,提出了动态链接。基本实现思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将他们链接在一起形成一个完整的程序,而不是像静态链接那样把所有的程序模块都链接成一个单独的可执行文件。所以动态链接是将链接过程推迟到了运行时才进行。
    #####同样,假如有程序1,程序2,和Lib.o三个文件,程序1和程序2在执行时都需要用到Lib.o文件,当运行程序1时,系统首先加载程序1,当发现需要Lib.o文件时,也同样加载到内存,再去加载程序2当发现也同样需要用到Lib.o文件时,则不需要重新加载Lib.o,只需要将程序2和Lib.o文件链接起来即可,内存中始终只存在一份Lib.o文件。
    这里写图片描述
    #####>注:详细关于动态库及动态链接可参考《程序员的自我修养——链接、装载与库》第七章。


    #####动态库和动态链接的例子依然使用上面的代码,输出结果也相同,唯一需要改变的就是Makefile文件。

    /Makefile/
    main : main.c libadd.so
    	gcc main.c -L . -ladd -o main
    
    libadd.so : 
    	gcc -fPIC -shared add.c -o libadd.so
    	//-shared表示输出结果是共享库类型的  -fPIC表示使用地址无关代码奇数来生产输出文件
    	
    .PHONY:clean
    clean:
    	rm main libadd.so
    

    #####注:<1>当我们生成可执行文件后,可使用ldd命令查看该可执行文件所依靠的动态库。
    这里写图片描述


    #####<2>前面提到windows和Linux下库文件的后缀不同,更根本的原因在于二者文件格式都不同。可以通过file一个动态库查看Linux下动态库的文件类型其实是ELF格式。ELF动态链接文件被称为动态共享对象(DSO,Dynamic Shared Objects),简称共享对象;在windows下,动态链接文件被称为动态链接库(Dynamic Linking Library),也就是.dll文件后缀的全称



    #####<3>优点:①毋庸置疑的就是节省内存;②减少物理页面的换入换出;③在升级某个模块时,理论上只需要将对应旧的目标文件覆盖掉即可。新版本的目标文件会被自动装载到内存中并且链接起来;④程序在运行时可以动态的选择加载各种程序模块,实现程序的扩展。


    图片截图来自《程序员的自我修养——链接、装载与库》

    展开全文
  • 一、基本概念1.1什么是库在windows平台linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制... 1.2库的种类linux下的库有两种:静态库和共享库(动态库)。二者的不同点在于代码被载入的时刻不同。静

    一、基本概念

    1.1什么是库

    在windows平台和linux平台下都大量存在着库。

    本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

    由于windows和linux的平台不同(主要是编译器、汇编器和连接器的不同),因此二者库的二进制是不兼容的。

    本文仅限于介绍linux下的库。

     

     

    1.2库的种类

    linux下的库有两种:静态库和共享库(动态库)。

    二者的不同点在于代码被载入的时刻不同。

    静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

    共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

     

     

    1.3库存在的意义

    库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。

    现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。

    共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

     

     

    1.4库文件是如何产生的在linux下

    静态库的后缀是.a,它的产生分两步

    Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表

    Step 2.ar命令将很多.o转换成.a,成为静态库

    动态库的后缀是.so,它由gcc加特定参数编译产生。

    具体方法参见后文实例。

     

    1.5库文件是如何命名的,有没有什么规范

    在linux下,库文件一般放在/usr/lib和/lib下,

    静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称

    动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号

     

     

    1.6如何知道一个可执行程序依赖哪些库

    ldd命令可以查看一个可执行程序依赖的共享库,

    例如# ldd /bin/lnlibc.so.6

    => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2

    => /lib/ld- linux.so.2 (0×40000000)

    可以看到ln命令依赖于libc库和ld-linux库

     

     

    1.7可执行程序在执行的时候如何定位共享库文件

    当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。

    此时就需要系统动态载入器(dynamic linker/loader)

    对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录找到库文件后将其载入内存

    如:export LD_LIBRARY_PATH=’pwd’

    将当前文件目录添加为共享目录

     

    1.8在新安装一个库之后如何让系统能够找到他

    如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

    如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下

    1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

    2.运行ldconfig,该命令会重建/etc/ld.so.cache文件


    二、用gcc生成静态和动态链接库的示例


    我们通常把一些公用函数制作成函数库,供其它程序使用。

    函数库分为静态库动态库两种。

     

    静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

     

    动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

     

    本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。

     

    为了便于阐述,我们先做一部分准备工作。

     

    2.1准备好测试代码add.h、add.c和test.c;

    add.h(见程序1)为该函数库的头文件。

     

    add.c(见程序2)是函数库的源程序,其中包含公用函数add,该函数将在屏幕上输出"uplooking"。

     

    test.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数add。

     

     程序1: add.h

    #ifndef __ADD_H__
    #define __ADD_H__
    
    #include <stdio.h>
    
    int add(int x, int y);
    
    
    #endif/*__ADD_H__*/


    程序2:add.c
    #include "add.h"
    
    int add(int x, int y)
    {
        printf("Hello Uplooking...\n");
    
        return x + y;
    }


    程序3:test.c
    #include "add.h"
    
    int main(void)
    {
        int x = 15;
        int y = 3;
    
        printf("x + y = %d\n", add(x, y));
    
    
        return 0;
    }


    2.2问题的提出

    注意:这个时候,我们编译好的add.o是无法通过gcc –o 编译的,这个道理非常简单,

    addc是一个没有main函数的.c程序,因此不够成一个完整的程序,如果使用gcc –o 编译并连接它,GCC将报错。

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

    这个时候我们有三种思路:

    1)  通过编译多个源文件,直接将目标代码合成一个.o文件。

    2)  通过创建静态链接库libadd.a,使得main函数调用add函数时可调用静态链接库。

    3)  通过创建动态链接库libadd.so,使得main函数调用add函数时可调用静态链接库。


    2.3思路一:编译多个源文件

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

    [root@deng test]# gcc -c add.c -o add.o

    为什么不使用gcc–o tes test.c 这个道理我们之前已经说了,使用-c是什么意思呢?这涉及到gcc 编译选项的常识。

     

    我们通常使用的gcc –o 是将.c源文件编译成为一个可执行的二进制代码(-o选项其实是制定输出文件文件名,如果不加-c选项,gcc默认会编译连接生成可执行文件,文件的名称有-o选项指定),这包括调用作为GCC内的一部分真正的C编译器(ccl),以及调用GNU C编译器的输出中实际可执行代码的外部GNU汇编器(as)和连接器工具(ld)。

    gcc –c是使用GNU汇编器将源文件转化为目标代码之后就结束,在这种情况下,只调用了C编译器(ccl)和汇编器(as),而连接器(ld)并没有被执行,所以输出的目标文件不会包含作为Linux程序在被装载和执行时所必须的包含信息,但它可以在以后被连接到一个程序。

    我们运行ls命令看看是否生存了test.o文件。

    # ls

    add.c add.h add.o test.c

     

    ls命令结果中,我们看到add.o文件,本步操作完成。

     

    同理编译test

    [root@deng test]# gcc -c test.c -o test.o

     

    将两个文件链接成一个.o文件。

    [root@deng test]# gcc test.o add.o -o test

     

    运行




    2.4思路二:静态链接库

     

    下面我们先来看看如何创建静态库,以及使用它。

     

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

     

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


     

    ls命令结果中有libadd.a

     

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

     

    在程序3:test.c中,我们包含了静态库的头文件add.h,然后在主程序main中直接调用公用函数add。下面先生成目标程序test,然后运行test程序看看结果如何。


     

    我们删除静态库文件试试公用函数add是否真的连接到目标文件 add中了。

     



     

    程序照常运行,静态库中的公用函数已经连接到目标文件中了。

    静态链接库的一个缺点是,如果我们同时运行了许多程序,并且它们使用了同一个库函数,这样,在内存中会大量拷贝同一库函数。这样,就会浪费很多珍贵的内存和存储空间。使用了共享链接库的Linux就可以避免这个问题。

    共享函数库和静态函数在同一个地方,只是后缀有所不同。比如,在一个典型的Linux系统,标准的共享数序函数库是/usr/lib/libm.so。

    当一个程序使用共享函数库时,在连接阶段并不把函数代码连接进来,而只是链接函数的一个引用。当最终的函数导入内存开始真正执行时,函数引用被解析,共享函数库的代码才真正导入到内存中。这样,共享链接库的函数就可以被许多程序同时共享,并且只需存储一次就可以了。共享函数库的另一个优点是,它可以独立更新,与调用它的函数毫不影响。


    2.5思路三、动态链接库(共享函数库)

     

    我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。

     

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

     

    在系统提示符下键入以下命令得到动态库文件libadd.so


     [root@deng test]# gcc --shared -fPIC -o libadd.so add.c
    [root@deng test]# ls
    add.c  add.h  bak  libadd.so  test.c
    [root@deng test]#


     “PIC”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译出的add.c可以被用于建立共享链接库。建立共享链接库只需要用GCC”-shared”标记即可。

     

    调用动态链接库编译目标文件。

     

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

     

    如果直接用如下方法进行编译,并连接:


    [root@deng test]# gcc test.c -o test -I. -L. -ladd

     

    (使用”-ladd”标记来告诉GCC驱动程序在连接阶段引用共享函数库libadd.so”-L.”标记告诉GCC函数库可能位于当前目录。否则GNU连接器会查找标准系统函数目录:它先后搜索

    1.elf文件的 DT_RPATH段

    2.环境变量LD_LIBRARY_PATH

    3./etc/ld.so.cache文件列表

    4./lib/,/usr/lib目录找到库文件后将其载入内存,但是我们生成的共享库在当前文件夹下,并没有加到上述的4个路径的任何一个中,因此,执行后会出现错误)

     

    [root@deng test]# ./test
    ./test: error while loading shared libraries: libadd.so: cannot open shared object file: No such file or directory
    [root@deng test]#


    错误提示,找不到动态库文件libadd.so。程序在运行时,会在/usr/lib/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。有多种方法可以解决,


    (1)我们将文件 libadd.so复制到目录/usr/lib中,再试试。

     

    [root@deng test]# cp libadd.so /usr/lib
    cp:是否覆盖"/usr/lib/libadd.so"? y
    [root@deng test]# ldconfig
    [root@deng test]# ./test
    Hello Uplooking...
    x + y = 18
    [root@deng test]#




    (2)既然连接器会搜寻LD_LIBRARY_PATH所指定的目录,那么我们可以将这个环境变量设置成当前目录:

    先执行:

    [root@deng test]# export LD_LIBRARY_PATH=$(pwd)
    [root@deng test]# ./test
    Hello Uplooking...
    x + y = 18
    [root@deng test]#

         
      注:   当用户在某个目录下面创建或拷贝了一个动态链接库,若想使其被系统共享,可以执行一下"ldconfig   目录名"这个命令.此命令的功能在于让ldconfig将指定目录下的动态链接库被系统共享起来,意即:在缓存文件/etc/ld.so.cache中追加进指定目录下的共享库.本例让系统共享了/usr/zhsoft/lib目录下的动态链接库.该命令会重建/etc/ld.so.cache文件

     


    下面的这个错误我没有遇到,不过也记录下,给遇到的人:

     {  这步后我没有成功,报错内容如下:/hello: error while loading shared libraries: /usr/lib/libmyhello.so: cannot restore segment prot after reloc: Permission denied

    google了一下,发现是SELinux搞的鬼,解决办法有两个:

    1.
        chcon -t texrel_shlib_t   
    /usr/lib/libmyhello.so
        (chcon -t texrel_shlib_t "你不能share的库的绝对路径")

    2.
        #vi /etc/sysconfig/selinux file
        或者用
        #gedit /etc/sysconfig/selinux file
        修改SELINUX=disabled
        重启

    }


    这也进一步说明了动态库在程序运行时是需要的。

     

    可以查看程序执行时调用动态库的过程:

    # ldd test
    执行 test,可以看到它是如何调用动态库中的函数的。

    [root@deng test]# ldd test
        linux-vdso.so.1 =>  (0x00007fffabdff000)
        libadd.so => /tmp/test/libadd.so (0x00007fecf17ce000)
        libc.so.6 => /lib64/libc.so.6 (0x000000333f200000)
        /lib64/ld-linux-x86-64.so.2 (0x000000333ea00000)
    [root@deng test]#


    我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,
    那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,
    来试试看。

    先删除除.c和.h外的所有文件,恢复成我们刚刚编辑完举例程序状态。

    # rm -f hello hello.o /usr/lib/libmyhello.so

    # ls

    hello.c hello.h main.c

    #

    在来创建静态库文件libmyhello.a和动态库文件libmyhello.so。

    # gcc -c hello.c

    # ar rcs libmyhello.a hello.o

    # gcc -shared -fPCI -o libmyhello.so hello.o

    # ls

    hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

    #

    通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.so都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标文件hello,并运行程序 hello。

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

    # ./hello

    ./hello: error while loading shared libraries: libmyhello.so: cannot open shar
    ed object file: No such file or directory

    #

    从程序hello运行的结果中很容易知道,当静态库和动态库同名时, gcc命令将优先使用动态库。

    Note:

    编译参数解析


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

    调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。


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

    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环境变量:指定程序动态链接库文件搜索路



    总结:

    创建并使用静态库

    第一步:编辑源文件,test.h test.c main.c。其中main.c文件中包含main函数,作为程序入口;test.c中包含main函数中需要用到的函数。

    vi test.h test.c main.c

    第二步:将test.c编译成目标文件。

    gcc -c test.c

    如果test.c无误,就会得到test.o这个目标文件。

    第三步:由.o文件创建静态库。

    ar rcs libtest.a test.o

    第四步:在程序中使用静态库。(顺序问题

    gcc -o main main.c -L. -ltest

    因为是静态编译,生成的执行文件可以独立于.a文件运行。

    第五步:执行。

    ./main

    创建并使用动态库

    第一步:编辑源文件,test.h test.c main.c。其中main.c文件中包含main函数,作为程序入口;test.c中包含main函数中需要用到的函数。

    vi test.h test.c main.c

    第二步:将test.c编译成目标文件。

    gcc -c test.c

    前面两步与创建静态库一致。

    第三步:由.o文件创建动态库文件。

    gcc -shared -fPIC -o libtest.so test.o

    第四步:在程序中使用动态库。

    gcc -o main main.c -L. -ltest

    当静态库和动态库同名时,gcc命令将优先使用动态库。

    第五步:执行。

    LD_LIBRARY_PATH=. ./main

    示例五 查看静态库中的文件

    [root@node56 lib]# ar -t libhycu.a

    base64.c.o

    binbuf.c.o

    cache.c.o

    chunk.c.o

    codec_a.c.o



    参考博客:http://blog.chinaunix.net/uid-26833883-id-3219335.html


    展开全文
  • 动态库静态库 库的链接方式:gcc / g++编译器默认的链接方式是动态链接 动态链接:链接动态库生成可执行程序,并没有把库中函数的实现指令直接拿过来写入可执行程序中,而是在可执行程序中记录了库中函数的符号...

    动态库与静态库

    库的链接方式:gcc / g++编译器默认的链接方式是动态链接
    动态链接:链接动态库生成可执行程序,并没有把库中函数的实现指令直接拿过来写入可执行程序中,而是在可执行程序中记录了库中函数的符号信息表,在运行可执行程序的时候再去加载动态库到内存中,如果动态库不存在,则程序无法运行。
    静态链接:链接静态库生成可执行程序,直接将库中我们用到的函数的实现代码指令,写入到了可执行程序文件中,程序运行的时候没有什么依赖。
    在这里插入图片描述
    动态链接的优缺点:生成的可执行文件比较小,运行时态库被加载到内存中,可以多个程序使用同一份内存中库函数代码;缺点是运行时需要依赖动态库的存在,不存在则无法运行,装载速度慢。

    静态链接的优缺点:程序运行没有其他依赖,可以直接运行;装载速度快,但是可执行程序比较大,并如果多个程序使用同一个库中的函数,则这个函数的代码在运行时内存就会有多份相同的库函数代码,会造成冗余。

    在我们写代码的时候,会有很多重复利用到的函数和代码,当打包成库,就可以在任何地方使用该函数和代码,这样子大大提高了我们的编程效率。现在我们来看看如何打包一个库函数

    动/静态库的打包与使用

    示例代码:
    child.c

    //child.c
    #include <stdio.h>
    
    int printChild()
    {
        printf("hello WhiteShirtI");
        return 0;
    }
    
    

    child.h

    //child.h
    int printChild();
    

    main.c

    //main.c
    #include <stdio.h>
    #include "child.h"
    
    int main()
    {
        printChild();
        return 0;
    }
    
    

    动态库

    1、将各个.c文件编译汇编成为目标文件
    gcc -c -fPIC child.c -o child.o
    2、打包成以.so为结尾的动态库
    gcc -share child.o -o libmychild.so ; 动态库的命名方式lib***.so
    在这里插入图片描述
    动态库的使用有3种方式
    生成可执行文件时链接使用gcc main.c -o main -lmychild -l指定库名称
    在这里插入图片描述
    但是我们发现说并找不到库文件,链接前还需要将我们的库配置好,动态库有3种方法
    1、将库文件放到指定路径下: /usr/lib64 or /usr/lib
    在这里插入图片描述
    但是放在系统库中会污染我门的原来的库
    2、设置链接库的搜索路径环境变量-将库文件所在路径添加进去:export LIBRARY_PATH=$LIBRARY_PATH:.
    在这里插入图片描述
    3、使用gcc -L选项指定链接库的搜索路径
    gcc main.c -o main -L./ -lmychild
    在这里插入图片描述
    ldd main 查看main这个可执行程序依赖的动态库
    在这里插入图片描述

    我们虽然可以链接成功,但是我们并不能成功执行main程序
    在这里插入图片描述

    运行可执行程序时加载使用方法
    1、将库文件放到指定路径下: /usr/lib64 or /usr/lib64
    在这里插入图片描述
    2、设置链接库的接在路径环境变量-将库文件所在路径添加进去:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
    在这里插入图片描述
    如果链接的是动态库,运行时就需要加载动态库;如果链接的是静态库,运行时就不需要加载

    静态库

    1、将各个.c文件编译汇编成为目标文件
    gcc -c child.c -o child1.o
    2、打包成以.a为结尾的静态库
    ar -cr libmyachild.a child1.o ; 静态库的命名方式lib***.a
    在这里插入图片描述
    如何让程序链接的是静态库:
    1、将静态库放到指定路径下
    gcc 默认使用动态库,那么我们如何让他使用静态库呢?
    将我们的静态库放到一个文件中,让它链接时去该目录下找,由于该目录只有静态库,此时就只能使用静态库gcc main.c -o main -L./lib -mychild
    在这里插入图片描述
    2、对于所有的库都使用静态链接:gcc -static main.c -o main -L./lib -lmychild
    在这里插入图片描述
    在新版本的linux 系统下安装 glibc-devel、glibc和gcc-c++时,都不会安装libc.a. 只安装libc.so. 所以当使用-static时,libc.a不能使用。只能报找不到libc了。
    解决方法:
    安装glibc-static
    sudo yum install glibc-static

    展开全文
  • 起因 理论功底 ...动态库和静态库 ...静态库和动态库如何构建加载 静态库和动态库依赖关系 Xcode 项目结构 iOS 依赖管理事实上的标准 解决问题 制作动态库
  • 本视频课程介绍C语言中动态库和静态库的基本概念,制作使用方法,手工加载动态库方法,如何导出函数类,以及VC的静态编译等等
  • 2 动态库静态库概念? 先回顾一下编译过程: 2.1 静态库 在链接阶段,链接器会将汇编生成的目标文件.o与引用到的静态库中的目标模块一起链接打包到可执行文件中,对应的链接方式称为静态链接。试想一下,...
  • Linux静态库和动态库

    千次阅读 2017-10-17 01:11:07
    2.2 静态库的创建使用 2.2.1 环境准备 2.2.2 生成静态库 2.2.3 生成可执行文件 三、动态库 3.1 概念 3.2 动态库的创建使用 3.2.1 环境准备 3.2.2 生成动态库 3.2.3 生成可执行文件 3.3 设置动态库的搜索...
  • java动态库和静态库

    千次阅读 2014-12-14 09:13:54
    这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。  为了克服这个缺点可以采用动态链接库。这个时候链接器仅仅是在可执行文件中打上标
  • 动态库静态库定义与比较  我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期的代码...
  • iOS - 动态库静态库的使用

    千次阅读 2016-11-17 11:08:47
    iOS静态库和动态库的运用
  • 静态库和动态库的生成调用

    千次阅读 2019-03-10 18:47:20
    基本概念 程序编译一般需经预处理、编译、 汇编链接几个步骤。在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件...**动态库:**DLL 是一个包含可由多个程序同时使用的代码数据的库...
  • Linux使用静态库和动态库

    千次阅读 2016-05-08 16:28:07
    Linux使用静态库和动态库
  • 静态库动态库,静态链接动态链接这几个概念理解起来很简单,本文主要是收集了网上的一些观点作了一个较全面的总结。 一、问题 1,静态库是什么? 2,动态库是什么? 3,两者的区别? 4,静态链接? 5...
  • 1.1、当我们建立一个项目(应用程序)它可以有很多种生成类型(应用程序.exe、动态库.dll、静态库lib),可以在创建向导时指定也可以在配置属性里更改。以vs2010为例,右键点击项目属性->配置属性->右侧配置类型中...
  • 理解静态库动态库 静态库 概念 静态库是指在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件;在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中的这种库 ...
  • Linux下gcc生成使用静态库和动态库详解

    万次阅读 多人点赞 2016-05-31 17:54:25
    Linux下gcc生成使用静态库和动态库详解(原文链接) 本文在原文的基础上做一些详细验证,部分稍有改动, 一、基本概念 1.1什么是库 1.2库的种类 1.3库存在的意义 1.4库文件是如何产生的在linux下 1.5库文件...
  • 1.概念和区别:  静态库就是在编译过程中一些目标文件的集合。静态库在程序链接的时候使用,链接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中。一旦链接完成,在执行程序的时候就不需要静态库了。 ...
  • linux下动态库和静态库引用问题解决

    千次阅读 2012-01-14 12:15:27
    linux下动态库和静态库引用问题解决 基本概念  库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。 例如:libhello.so libhello.a  为了在同一系统中使用不同版本的库,可以在库文件名后...
  • 文件的概念  在很多情况下,源代码文件也可以被多个程序共享。因此要降低工作量的第一步就是将这些源代码文件只编译一次,然后在需要的时候将它们链接进不同的可执行文件中。虽然这项技术能够节省编译时间,但其...
  • 什么是库 在windows平台linux平台下都大量存在着库。...linux下的库有两种:静态库和共享库(动态库)。 二者的不同点在于代码被载入的时刻不同。 – 静态库的代码在编译过程中已经被载入可...
  • Windows下的静态库和动态库

    千次阅读 2017-10-25 14:37:03
    缺少xxx.dll.....”,想必大家都碰见过这样的错误,但是很抱歉,在这里并不会讲具体怎么解决这个错误,只是借这个错误引出“动态库”(这个xxx.dll就是一个动态库),借“动态库”引出静态库概念。 在使用C/C++...
  • Linux编程——静态库和动态库

    千次阅读 2015-11-13 19:16:42
    库可以分为两种:静态库和动态库 静态库静态库就是一些目标文件的集合,以.a结尾。静态库在程序链接的时候使用,链接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中。一旦链接完成,在执行程序的时候就...
  • iOS静态库和动态库

    2019-05-21 12:32:09
    一、静态库和动态库的区别 库:是资源文件代码编译的一个集合 静态库: 静态库是在编译时,完整的拷贝至可执行文件中,被多次使用就有多次冗余拷贝; 动态库: 程序运行时由系统动态加载到内存,而不是复制,供程序...
  • 动态库链接boost静态库

    千次阅读 2018-08-21 20:42:59
    2. c++库静态链接 1,2点的改变如下,强制链静态库的方法为参数下为-l:libXXXX.a; 对于boost log, 需要将宏-DBOOST_LOG_DYN_LINK去掉 LOCAL_STATICLIBS := boost_log boost_log_setup boost_system boost...
  • 库是代码共享的主要方式,动态库和静态库的主要区别在于他们链接形式的不同(静态动态链接),它们都是目标文件的集合,再加上一些索引表项来表征各文件的信息。通常,linux里目标文件是ELF格式,而win则为PE 静态...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 121,673
精华内容 48,669
关键字:

动态库和静态库的概念