C# “静态链接”和“动态链接”是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/311882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 22:43:20  来源:igfitidea点击:

What do 'statically linked' and 'dynamically linked' mean?

c#c++linkerstatic-linkingdynamic-linking

提问by UnkwnTech

I often hear the terms 'statically linked' and 'dynamically linked', often in reference to code written in C, C++or C#. What are they, what exactly are they talking about, and what are they linking?

我经常听到“静态链接”和“动态链接”这两个术语,通常指的是用CC++C#编写的代码。它们是什么,它们究竟在谈论什么,它们在连接什么?

采纳答案by paxdiablo

There are (in most cases, discounting interpreted code) two stages in getting from source code (what you write) to executable code (what you run).

从源代码(您编写的内容)到可执行代码(您运行的内容)有两个阶段(在大多数情况下,不考虑解释代码)。

The first is compilation which turns source code into object modules.

第一个是将源代码转换为目标模块的编译。

The second, linking, is what combines object modules together to form an executable.

第二个,链接,是将目标模块组合在一起形成一个可执行文件。

The distinction is made for, among other things, allowing third party libraries to be included in your executable without you seeing their source code (such as libraries for database access, network communications and graphical user interfaces), or for compiling code in different languages (C and assembly code for example) and then linking them all together.

区别在于,允许将第三方库包含在您的可执行文件中而不查看其源代码(例如用于数据库访问、网络通信和图形用户界面的库),或用于编译不同语言的代码(例如 C 和汇编代码),然后将它们链接在一起。

When you staticallylink a file into an executable, the contents of that file are included at link time. In other words, the contents of the file are physically inserted into the executable that you will run.

当您将文件静态链接到可执行文件时,该文件的内容将在链接时包含在内。换句话说,文件的内容被物理插入到您将运行的可执行文件中。

When you link dynamically, a pointer to the file being linked in (the file name of the file, for example) is included in the executable and the contents of said file are not included at link time. It's only when you later runthe executable that these dynamically linked files are bought in and they're only bought into the in-memory copy of the executable, not the one on disk.

当您动态链接时,指向被链接文件的指针(例如文件的文件名)包含在可执行文件中,并且在链接时不包含所述文件的内容。只有当您稍后运行可执行文件时,才会购买这些动态链接文件,并且它们只会购买到可执行文件的内存副本中,而不是磁盘上的副本中。

It's basically a method of deferred linking. There's an even moredeferred method (called late binding on some systems) that won't bring in the dynamically linked file until you actually try to call a function within it.

它基本上是一种延迟链接的方法。还有一种延迟的方法(在某些系统上称为后期绑定),它不会引入动态链接的文件,直到您实际尝试调用其中的函数。

Statically-linked files are 'locked' to the executable at link time so they never change. A dynamically linked file referenced by an executable can change just by replacing the file on the disk.

静态链接的文件在链接时被“锁定”到可执行文件,因此它们永远不会改变。可执行文件引用的动态链接文件只需替换磁盘上的文件即可更改。

This allows updates to functionality without having to re-link the code; the loader re-links every time you run it.

这允许更新功能而无需重新链接代码;加载程序每次运行时都会重新链接。

This is both good and bad - on one hand, it allows easier updates and bug fixes, on the other it can lead to programs ceasing to work if the updates are incompatible - this is sometimes responsible for the dreaded "DLL hell" that some people mention in that applications can be broken if you replace a dynamically linked library with one that's not compatible (developers who do this should expect to be hunted down and punished severely, by the way).

这有好有坏 - 一方面,它允许更容易的更新和错误修复,另一方面,如果更新不兼容,它可能导致程序停止工作 - 这有时是某些人可怕的“DLL 地狱”的原因如果您将动态链接库替换为不兼容的库,则应用程序可能会被破坏(顺便说一下,这样做的开发人员应该会受到追捕和严厉惩罚)。



As an example, let's look at the case of a user compiling their main.cfile for static and dynamic linking.

作为一个例子,让我们看一下用户编译他们的main.c文件以进行静态和动态链接的情况。

Phase     Static                    Dynamic
--------  ----------------------    ------------------------
          +---------+               +---------+
          | main.c  |               | main.c  |
          +---------+               +---------+
Compile........|.........................|...................
          +---------+ +---------+   +---------+ +--------+
          | main.o  | | crtlib  |   | main.o  | | crtimp |
          +---------+ +---------+   +---------+ +--------+
Link...........|..........|..............|...........|.......
               |          |              +-----------+
               |          |              |
          +---------+     |         +---------+ +--------+
          |  main   |-----+         |  main   | | crtdll |
          +---------+               +---------+ +--------+
Load/Run.......|.........................|..........|........
          +---------+               +---------+     |
          | main in |               | main in |-----+
          | memory  |               | memory  |
          +---------+               +---------+

You can see in the static case that the main program and C runtime library are linked together at link time (by the developers). Since the user typically cannot re-link the executable, they're stuck with the behaviour of the library.

您可以在静态情况下看到主程序和 C 运行时库在链接时链接在一起(由开发人员)。由于用户通常无法重新链接可执行文件,因此他们会被库的行为所困扰。

In the dynamic case, the main program is linked with the C runtime import library (something which declares what's in the dynamic library but doesn't actually defineit). This allows the linker to link even though the actual code is missing.

在动态情况下,主程序与 C 运行时导入库链接(声明动态库中的内容但实际上并未定义它的东西)。即使缺少实际代码,这也允许链接器进行链接。

Then, at runtime, the operating system loader does a late linking of the main program with the C runtime DLL (dynamic link library or shared library or other nomenclature).

然后,在运行时,操作系统加载器将主程序与 C 运行时 DLL(动态链接库或共享库或其他命名法)进行后期链接。

The owner of the C runtime can drop in a new DLL at any time to provide updates or bug fixes. As stated earlier, this has both advantages and disadvantages.

C 运行时的所有者可以随时插入新的 DLL 以提供更新或错误修复。如前所述,这既有优点也有缺点。

回答by John D. Cook

Statically linked libraries are linked in at compile time. Dynamically linked libraries are loaded at run time. Static linking bakes the library bit into your executable. Dynamic linking only bakes in a reference to the library; the bits for the dynamic library exist elsewhere and could be swapped out later.

静态链接库在编译时链接。动态链接库在运行时加载。静态链接将库位烘焙到您的可执行文件中。动态链接只包含对库的引用;动态库的位存在于其他地方,以后可以换出。

回答by artificialidiot

(I don't know C# but it is interesting to have a static linking concept for a VM language)

(我不知道 C#,但是对于 VM 语言有一个静态链接概念很有趣)

Dynamic linking involves knowing how to find a required functionality which you only have a reference from your program. You language runtime or OS search for a piece of code on the filesystem, network or compiled code cache, matching the reference, and then takes several measures to integrate it to your program image in the memory, like relocation. They are all done at runtime. It can be done either manually or by the compiler. There is ability to update with a risk of messing up (namely, DLL hell).

动态链接涉及了解如何查找所需的功能,而您只能从您的程序中找到该功能的参考。您的语言运行时或操作系统在文件系统、网络或编译后的代码缓存中搜索一段代码,匹配引用,然后采取多种措施将其集成到内存中的程序映像中,例如重定位。它们都是在运行时完成的。它可以手动完成,也可以由编译器完成。有更新的能力,但有搞砸的风险(即 DLL 地狱)。

Static linking is done at compile time that, you tell the compiler where all the functional parts are and instruct it to integrate them. There are no searching, no ambiguity, no ability to update without a recompile. All your dependencies are physically one with your program image.

静态链接是在编译时完成的,你告诉编译器所有功能部件在哪里,并指示它集成它们。没有搜索,没有歧义,没有重新编译的更新能力。您的所有依赖项与您的程序映像在物理上是一体的。

回答by Artelius

I think a good answer to this question ought to explain what linking is.

我认为一个好的答案,这个问题应该解释链接什么

When you compile some C code (for instance), it is translated to machine language. Just a sequence of bytes which, when run, causes the processor to add, subtract, compare, "goto", read memory, write memory, that sort of thing. This stuff is stored in object (.o) files.

当你编译一些 C 代码(例如)时,它被翻译成机器语言。只是一个字节序列,当运行时,它会导致处理器进行加、减、比较、“转到”、读取内存、写入内存之类的事情。这些东西存储在对象 (.o) 文件中。

Now, a long time ago, computer scientists invented this "subroutine" thing. Execute-this-chunk-of-code-and-return-here. It wasn't too long before they realised that the most useful subroutines could be stored in a special place and used by any program that needed them.

现在,很久以前,计算机科学家发明了这个“子程序”的东西。在此处执行此代码块并返回。不久之后,他们意识到最有用的子程序可以存储在一个特殊的地方,并被任何需要它们的程序使用。

Now in the early days programmers would have to punch in the memory address that these subroutines were located at. Something like CALL 0x5A62. This was tedious and problematic should those memory addresses ever need to be changed.

现在,在早期,程序员必须输入这些子程序所在的内存地址。类似的东西CALL 0x5A62。如果这些内存地址需要更改,这将是乏味且有问题的。

So, the process was automated. You write a program that calls printf(), and the compiler doesn't know the memory address of printf. So the compiler just writes CALL 0x0000, and adds a note to the object file saying "must replace this 0x0000 with the memory location of printf".

所以,这个过程是自动化的。您编写了一个调用 的程序printf(),而编译器不知道 的内存地址printf。所以编译器只写CALL 0x0000,并在目标文件中添加一个注释,说“必须用printf的内存位置替换这个 0x0000 ”。

Static linkage means that the linker program (the GNU one is called ld) adds printf's machine code directly to your executable file, and changes the 0x0000 to the address of printf. This happens when your executable is created.

静态链接是指链接器程序(GNU 中称为ld)将printf的机器码直接添加到您的可执行文件中,并将 0x0000 更改为printf. 创建可执行文件时会发生这种情况。

Dynamic linkage means that the above step doesn't happen. The executable file stillhas a note that says "must replace 0x000 with the memory location of printf". The operating system's loader needs to find the printf code, load it into memory, and correct the CALL address, each time the program is run.

动态联动意味着上述步骤不会发生。可执行文件还有一条注释说“必须用printf的内存位置替换0x000”。每次运行程序时,操作系统的加载器都需要找到 printf 代码,将其加载到内存中,并更正 CALL 地址。

It's common for programs to call some functions which will be statically linked (standard library functions like printfare usually statically linked) and other functions which are dynamically linked. The static ones "become part" of the executable and the dynamic ones "join in" when the executable is run.

程序通常会调用一些静态链接的函数(标准库函数printf通常是静态链接的)和其他动态链接的函数。当可执行文件运行时,静态的“成为”可执行文件的一部分,而动态的“加入”。

There are advantages and disadvantages to both methods, and there are differences between operating systems. But since you didn't ask, I'll end this here.

两种方法各有优缺点,操作系统之间也存在差异。但既然你没有问,我就到此为止了。

回答by Artelius

Because none of the above posts actually show howto statically link something and see that you did it correctly so I will address this issue:

因为以上帖子都没有真正展示如何静态链接某些内容并查看您是否正确执行了操作,所以我将解决这个问题:

A simple C program

一个简单的 C 程序

#include <stdio.h>

int main(void)
{
    printf("This is a string\n");
    return 0;
}

Dynamically link the C program

动态链接 C 程序

gcc simpleprog.c -o simpleprog

And run fileon the binary:

file在二进制文件上运行:

file simpleprog 

And that will show it is dynamically linked something along the lines of:

这将表明它是按照以下方式动态链接的:

"simpleprog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xf715572611a8b04f686809d90d1c0d75c6028f0f, not stripped"

“simpleprog:ELF 64 位 LSB 可执行文件,x86-64,版本 1 (SYSV),动态链接(使用共享库),适用于 GNU/Linux 2.6.26,BuildID[sha1]=0xf715572611a8b04f686809d90d1c0d75c6,未剥离

Instead let us statically link the program this time:

这次让我们静态链接程序:

gcc simpleprog.c -static -o simpleprog

Running file on this statically linked binary will show:

在这个静态链接的二进制文件上运行文件将显示:

file simpleprog 

"simpleprog: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.26, BuildID[sha1]=0x8c0b12250801c5a7c7434647b7dc65a644d6132b, not stripped"

“simpleprog:ELF 64 位 LSB 可执行文件,x86-64,版本 1(GNU/Linux),静态链接,用于 GNU/Linux 2.6.26,BuildID[sha1]=0x8c0b12250801c5a7c7434647b7dc65a644d6132”

And you can see it is happily statically linked. Sadly however not all libraries are simple to statically link this way and may require extended effort using libtoolor linking the object code and C libraries by hand.

你可以看到它是愉快地静态链接的。然而遗憾的是,并非所有库都可以简单地以这种方式静态链接,并且可能需要libtool手动使用或链接目标代码和 C 库。

Luckily many embedded C libraries like musloffer static linking options for nearly all if not allof their libraries.

幸运的是,许多嵌入式 C 库musl都为几乎所有(如果不是全部)库提供静态链接选项。

Now stracethe binary you have created and you can see that there are no libraries accessed before the program begins:

现在strace您已经创建了二进制文件,您可以看到在程序开始之前没有访问任何库:

strace ./simpleprog

Now compare with the output of straceon the dynamically linked program and you will see that the statically linked version's strace is much shorter!

现在与strace动态链接程序上的输出进行比较,您将看到静态链接版本的 strace 更短!