精华内容
参与话题
问答
  • 静态链接和动态链接

    2019-02-14 14:00:44
    然后进行编译,这个过程主要是进行词法分析、语法分析语义分析等,生成*.s的汇编文件;最后进行汇编,这个过程比较简单,就是将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件。以上就是编译的过程...

    首先大概介绍一下,编译分为3步,首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件;然后进行编译,这个过程主要是进行词法分析、语法分析和语义分析等,生成*.s的汇编文件;最后进行汇编,这个过程比较简单,就是将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件。以上就是编译的过程,下面主要介绍两种链接方式--静态链接和动态链接。

            静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时,下面来详细介绍这两种链接方式。

    一、静态链接
    1.为什么要进行静态链接
            在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个*.c文件会形成一个*.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接

    2.静态链接的原理
             由很多目标文件进行链接形成的是静态库,反之静态库也可以简单地看成是一组目标文件的集合,即很多目标文件经过压缩打包后形成的一个文件,如下图,使用ar命令的-a参数查看静态库的组成:

            这里的*.o目标文件在我前面的博客《从编写源代码到程序在内存中运行的全过程解析》中已经讲的很清楚了,不清楚的可以看一下。

            以下面这个图来简单说明一下从静态链接到可执行文件的过程,根据在源文件中包含的头文件和程序中使用到的库函数,如stdio.h中定义的printf()函数,在libc.a中找到目标文件printf.o(这里暂且不考虑printf()函数的依赖关系),然后将这个目标文件和我们hello.o这个文件进行链接形成我们的可执行文件。

            这里有一个小问题,就是从上面的图中可以看到静态运行库里面的一个目标文件只包含一个函数,如libc.a里面的printf.o只有printf()函数,strlen.o里面只有strlen()函数。

            我们知道,链接器在链接静态链接库的时候是以目标文件为单位的。比如我们引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来,如果很多函数都放在一个目标文件中,很可能很多没用的函数都被一起链接进了输出结果中。由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,那些没有被用到的目标文件就不要链接到最终的输出文件中。


    3.静态链接的优缺点
            静态链接的缺点很明显,一是浪费空间,因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有printf.o,所以同一个目标文件都在内存存在多个副本;另一方面就是更新比较困难,因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。

    问题:

    二、动态链接
    1.为什么会出现动态链接
            动态链接出现的原因就是为了解决静态链接中提到的两个问题,一方面是空间浪费,另外一方面是更新困难。下面介绍一下如何解决这两个问题。

    2.动态链接的原理
            动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。下面简单介绍动态链接的过程:

            假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接(这个链接过程和静态链接类似)形成可执行程序。

    3.动态链接的优缺点
            动态链接的优点显而易见,就是即使需要每个程序都依赖同一个库,但是该库不会像静态链接那样在内存中存在多分,副本,而是这多个程序在执行时共享同一份副本;另一个优点是,更新也比较方便,更新时只需要替换原来的目标文件,而无需将所有的程序再重新链接一遍。当程序下一次运行时,新版本的目标文件会被自动加载到内存并且链接起来,程序就完成了升级的目标。但是动态链接也是有缺点的,因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失。

            据估算,动态链接和静态链接相比,性能损失大约在5%以下。经过实践证明,这点性能损失用来换区程序在空间上的节省和程序构建和升级时的灵活性是值得的。

    4.动态链接地址是如何重定位的呢?
            前面我们讲过静态链接时地址的重定位,那我们现在就在想动态链接的地址又是如何重定位的呢?虽然动态链接把链接过程推迟到了程序运行时,但是在形成可执行文件时(注意形成可执行文件和执行程序是两个概念),还是需要用到动态链接库。比如我们在形成可执行程序时,发现引用了一个外部的函数,此时会检查动态链接库,发现这个函数名是一个动态链接符号,此时可执行程序就不对这个符号进行重定位,而把这个过程留到装载时再进行。
     

    展开全文
  • 静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器或汇编器生成)链接到一块生成可执行程序。 动态链接英文是Dynamic Linking...

    静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器汇编器生成)链接到一块生成可执行程序。


    动态链接英文是Dynamic Linking需要解决空间浪费和更新困难这两个问题最简单的办法就是把程序的模块相互划分开来,形成独立的文件,而不再将他们静态的链接在一起。简单地讲,就是不对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接。也就是说,把链接这个过程推迟到了运行时再进行,这就是动态链接(Dynamic Linking)的基本思想。


    动态链接,在可执行文件装载时或运行时,由操作系统的装载程序加载库。大多数操作系统将解析外部引用(比如库)作为加载过程的一部分。在这些系统上,可执行文件包含一个叫做import directory的表,该表的每一项包含一个库的名字。根据表中记录的名字,装载程序在硬盘上搜索需要的库,然后将其加载到内存中预先不确定的位置,之后根据加载库后确定的库的地址更新可执行程序。可执行程序根据更新后的库信息调用库中的函数或引用库中的数据。这种类型的动态加载成为装载时加载 ,被包括Windows和Linux的大多数系统采用。

    展开全文
  • 深入浅出静态链接和动态链接

    万次阅读 多人点赞 2018-05-06 09:24:48
    作为一名C/C++程序员,对于编译链接的过程要了然于胸。首先大概介绍一下,编译分为3步,首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件;...

            作为一名C/C++程序员,对于编译链接的过程要了然于胸。首先大概介绍一下,编译分为3步,首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件;然后进行编译,这个过程主要是进行词法分析、语法分析和语义分析等,生成*.s的汇编文件;最后进行汇编,这个过程比较简单,就是将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件。以上就是编译的过程,下面主要介绍两种链接方式--静态链接和动态链接。

            静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时,下面来详细介绍这两种链接方式。

    一、静态链接

    1.为什么要进行静态链接

            在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个*.c文件会形成一个*.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接

    2.静态链接的原理

             由很多目标文件进行链接形成的是静态库,反之静态库也可以简单地看成是一组目标文件的集合,即很多目标文件经过压缩打包后形成的一个文件,如下图,使用ar命令的-a参数查看静态库的组成:


            这里的*.o目标文件在我前面的博客《从编写源代码到程序在内存中运行的全过程解析》中已经讲的很清楚了,不清楚的可以看一下。

            以下面这个图来简单说明一下从静态链接到可执行文件的过程,根据在源文件中包含的头文件和程序中使用到的库函数,如stdio.h中定义的printf()函数,在libc.a中找到目标文件printf.o(这里暂且不考虑printf()函数的依赖关系),然后将这个目标文件和我们hello.o这个文件进行链接形成我们的可执行文件。


            这里有一个小问题,就是从上面的图中可以看到静态运行库里面的一个目标文件只包含一个函数,如libc.a里面的printf.o只有printf()函数,strlen.o里面只有strlen()函数。

            我们知道,链接器在链接静态链接库的时候是以目标文件为单位的。比如我们引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来,如果很多函数都放在一个目标文件中,很可能很多没用的函数都被一起链接进了输出结果中。由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,那些没有被用到的目标文件就不要链接到最终的输出文件中。

    3.静态链接的优缺点

            静态链接的缺点很明显,一是浪费空间,因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有printf.o,所以同一个目标文件都在内存存在多个副本;另一方面就是更新比较困难,因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。

    问题:

    二、动态链接
    1.为什么会出现动态链接

            动态链接出现的原因就是为了解决静态链接中提到的两个问题,一方面是空间浪费,另外一方面是更新困难。下面介绍一下如何解决这两个问题。

    2.动态链接的原理

            动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。下面简单介绍动态链接的过程:

            假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接(这个链接过程和静态链接类似)形成可执行程序。

    3.动态链接的优缺点

            动态链接的优点显而易见,就是即使需要每个程序都依赖同一个库,但是该库不会像静态链接那样在内存中存在多分,副本,而是这多个程序在执行时共享同一份副本;另一个优点是,更新也比较方便,更新时只需要替换原来的目标文件,而无需将所有的程序再重新链接一遍。当程序下一次运行时,新版本的目标文件会被自动加载到内存并且链接起来,程序就完成了升级的目标。但是动态链接也是有缺点的,因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失。

            据估算,动态链接和静态链接相比,性能损失大约在5%以下。经过实践证明,这点性能损失用来换区程序在空间上的节省和程序构建和升级时的灵活性是值得的。

    4.动态链接地址是如何重定位的呢?

            前面我们讲过静态链接时地址的重定位,那我们现在就在想动态链接的地址又是如何重定位的呢?虽然动态链接把链接过程推迟到了程序运行时,但是在形成可执行文件时(注意形成可执行文件和执行程序是两个概念),还是需要用到动态链接库。比如我们在形成可执行程序时,发现引用了一个外部的函数,此时会检查动态链接库,发现这个函数名是一个动态链接符号,此时可执行程序就不对这个符号进行重定位,而把这个过程留到装载时再进行。

    展开全文
  • 上一篇文章已经讲过了window系统下如何制作使用静态链接和动态链接库, 这篇文章我们来看一下在Mac系统(Linux系统也是一样)下面如何制作静态链接和动态链接库 太长不看版 假设我们有一个util.cpp文件和main.cpp...

    上一篇文章已经讲过了window系统下如何制作使用静态链接库和动态链接库, 这篇文章我们来看一下在Mac系统(Linux系统也是一样)下面如何制作静态链接库和动态链接库

    太长不看版

    假设我们有一个util.cpp文件和main.cpp文件,在main文件中调用util.cpp文件中定义的函数。我们把util.cpp文件制作成静态库和动态库。

    1. 生成目标文件
    g++ -c util.cpp -o util.o
    
    1. 打包静态库
    ar crv libutil.a util.o
    
    1. 生成动态库
    g++ -shared -fPIC -o libutil.so util.o
    
    1. 使用静态库
    g++ -g main.cpp libutil.a -o a.out
    
    1. 使用动态库
    g++ -g -std=c++11 main.cpp -L. -lutil -o a.out
    

    当然,以上这几条指令如果你觉得繁琐的话,也可以写到一个makefile文件一键执行

    target:
    	mkdir -p output
    	g++ -c util.cpp -o ./output/util.o -std=c++11
    	ar crv ./output/libutil.a ./output/util.o
    	g++ -shared -fPIC -o ./output/libutil.so ./output/util.o
    	rm ./output/util.o
    	g++ -g main.cpp ./output/libutil.a -o a.out -std=c++11
    	#g++ -g -std=c++11 main.cpp -L./output -lutil -o a.out
    	rm -rf *.dSYM
    clean:
    	rm -rf ./output *.out *.dSYM
    

    所需文件

    1. main.cpp

    //main.cpp
    #include<iostream>
    #include "util.h"
    using namespace std;
    int main()
    {
        cout << "hello, world!" << endl;
        cout << Util::add(1, 2) << endl;
        std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        cout << Util::sum(nums) << endl;
        return 0;
    }
    

    2.util.h

    #include<string>
    #include<vector>
    class Util {
    public:
        static int add(int a, int b);
        static int sum(const std::vector<int>& nums);
    };
    

    3. util.cpp

    #include "util.h"
    int Util::add(int a, int b)
    {
        return a + b;
    }
    
    int Util::sum(const std::vector<int>& nums)
    {
        int ans = 0;
        for (auto it : nums) {
            ans += it;
        }
        return ans;
    } 
    
    展开全文
  • 1.1、当我们建立一个项目(应用程序)它可以有很多种生成类型(应用程序.exe、动态库.dll、静态库lib),可以在创建向导时指定也可以在配置属性里更改。以vs2010为例,右键点击项目属性->配置属性->右侧配置类型中...
  • 静态链接和动态链接区别

    千次阅读 2019-09-22 22:17:18
    在链接过程中,静态链接和动态链接就出现了区别。静态链接的过程就已经把要链接的内容已经链接到了生成的可执行文件中,就算你在去把静态库删除也不会影响可执行程序的执行;而动态链接这个过程却没有把内容链接...
  • 静态链接动态链接;静态库和动态库 分类: Linux编程 2011-08-31 23:31 555人阅读 评论(1) 收藏 举报 dll编程callbackexelibraryfunction 静态编译:将所有的dll和主程序都编译到一个主程序里面。 动态编译:...
  • 静态库与动态库。 动态库、静态库是其他语言中也都有对应概念的东西,也是一通百通的。C#中的 Assembly、Java 中的jar 等。 静态库:编译时代码编译进exe 中,会使得程序体积非常庞大。不利于模块的共 享,...
  • 静态库,动态库,静态链接和动态链接这几个概念理解起来很简单,本文主要是收集了网上的一些观点作了一个较全面的总结。 一、问题 1,静态库是什么? 2,动态库是什么? 3,两者的区别? 4,静态链接? 5...
  • 什么是虚拟现实,什么是增强现实?
  • ldd a.out 查看依赖的库文件(动态和静态库都可以看到)

空空如也

1 2 3 4 5 ... 20
收藏数 8,050
精华内容 3,220
关键字:

静态链接和动态链接