简体   繁体   English

使用gcc进行静态和动态链接

[英]static and dynamic linking using gcc

I've been recently reading about static and dynamic linking and I understood the differences and how to create static and dynamic library and link it to my project 我最近一直在阅读有关静态和动态链接的信息,我了解它们之间的区别以及如何创建静态和动态库并将其链接到我的项目

But, a question came to my mind that I couldn't answer or find answer for it as It's a specific question ... when I compile my code on linux using the line 但是,我想到一个问题,我无法回答或找到答案,因为这是一个特定的问题……当我使用以下代码在linux上编译代码时

#include <stdio.h>
int main()
{
  printf("hello, world!\n");
}

compiling using this command 使用此命令进行编译

[root@host ~]# gcc helloworld.c -o helloworld

which type of linking is this?? 这是哪种链接? so the stdio.h is statically or dynamically linked to my project??? 所以stdio.h是静态或动态链接到我的项目的???

Libraries are mostly used as shared resources so, that several different programs can reuse the same pre-compiled code in some manner. 库主要用作共享资源,因此几个不同的程序可以以某种方式重用相同的预编译代码。 Some libraries come as standard libraries which are delivered with the operating system and/or the compiler package. 一些库作为标准库提供,它们随操作系统和/或编译器软件包一起提供。 Some libraries come with other third party projects. 一些图书馆还带有其他第三方项目。

When you run just gcc in the manner of your example, you really run a compiler driver which provides you with few compilation-related functions, calling different parts of the compilation process and finally linking your application with a few standard libraries. 当以示例方式仅运行gcc时,实际上就是在运行一个编译器驱动程序,该驱动程序为您提供了一些与编译相关的功能,调用了编译过程的不同部分,最后将您的应用程序与一些标准库链接在一起。 The type of the libraries is chosen based on the qualifiers you provide. 库的类型是根据您提供的限定符选择的。 By default it will try to find dynamic (shared) libraries and if missing will attempt for static. 默认情况下,它将尝试查找动态(共享)库,如果缺少,将尝试使用静态库。 Unless you tell it to use static libs only (-static). 除非您告诉它仅使用静态库(-static)。

When you link to project libraries you tell the gcc/g++ which libraries to use in a manner (-lname). 当您链接到项目库时,您告诉gcc / g ++使用哪种库(-lname)。 In such a way it will do the same as with the standard libraries, looking for '.so' first and '.a' second, unless -static is used. 这样,它将与标准库相同,除非使用-static,否则首先查找“ .so”,然后查找“ .a”。 You can directly specify the path to the full library name as well, actually telling it which library to use. 您也可以直接指定完整库名的路径,实际上告诉它要使用哪个库。 There are several other qualifiers which control the linking process, please look man for 'g++' and 'ld'. 还有其他几个限定链接过程的限定符,请在man中查找'g ++'和'ld'。

A library must contain real program code and data. 库必须包含真实的程序代码和数据。 The way it is linked to the main executable (and other libraries) is through symbol tables which are parts of the libraries. 它链接到主要可执行文件(和其他库)的方式是通过符号表(它们是库的一部分)进行的。 A symbol table contains entries for global functions an data. 符号表包含用于全局函数的数据条目。

There is a slight difference in the structure of the shared and static libs. 共享库和静态库的结构略有不同。 The former one is actually a pre-linked object, similar to an executable image with some extra info related to the symbols and relocation (such a library can be loaded at any address in the memory and still should work correctly). 前一个实际上是一个预链接的对象,类似于一个可执行映像,带有一些与符号和重定位有关的额外信息(此类库可以加载到内存中的任何地址,并且仍然可以正常工作)。 The static library is actually an archive of '.o' files, ready for a full-blown linking. 静态库实际上是'.o'文件的存档,可以进行完整的链接。

The usual steps to create a library is to compile multiple parts of your program into '.o' files which in turn could be linked in a shared library by 'ld' (or g++) or archived in .a with 'ar'. 创建库的通常步骤是将程序的多个部分编译为“ .o”文件,这些文件又可以通过“ ld”(或g ++)链接到共享库中,或通过“ ar”存储在.a中。 Afterwards you can use them for linking in a manner described above. 之后,您可以使用它们以上述方式进行链接。

An object file (.o) is created one per a .cpp source file. 每个.cpp源文件创建一个目标文件(.o)。 The source file contains code and can include any number of header files, as 'stdio.h' in your case (or cstdio) or whatever. 源文件包含代码,并且可以包含任意数量的头文件,在您的情况下(或cstdio)为“ stdio.h”或类似名称。 These files become a part of the source which is insured by the cpp preprocessor. 这些文件成为由cpp预处理程序保障的源文件的一部分。 The latter takes care of macros and flattening all the #include hierarchies so that the compiler sees only a single text stream which it converts into '.o'. 后者负责宏并展平所有#include层次结构,以便编译器仅看到单个文本流,并将其转换为“ .o”。 In general header files should not contain executable code, but declarations and macros, though it is not always true. 通常,头文件不应包含可执行代码,而应包含声明和宏,尽管并非总是如此。 But it does not matter since they become welded with the main source file. 但这并不重要,因为它们已与主源文件融合在一起。

Hope this would explain it. 希望这能解释它。

which type of linking is this?? 这是哪种链接? so the stdio.h is statically or dynamically linked to my project??? 所以stdio.h是静态或动态链接到我的项目的???

stdio.h is not linked, it is a header file, and contains code / text, no compiled objects. stdio.h未链接,它是头文件,并且包含代码/文本,没有编译的对象。

The normal link process prefers the '.so' library over the '.a' archive when both are found in the same directory. 当两个链接都位于同一目录中时,普通链接过程相对于“ .a”存档更喜欢使用“ .so”库。 Your simple command is linking with the .so (if that is in the correct path) or the .a (if that is found in a path with no .so equivalent). 您的简单命令是与.so(如果在正确的路径中)或.a(如果在没有.so等效项的路径中找到)链接。

To achieve static linking, you have several choices, including 要实现静态链接,您有几种选择,包括

1) copy the '.a' archive to a directory you create, then specify that 
directory (-L)

2) specify the path to the '.a' in the build command.   Boost example:

$(CC) $(CC_FLAGS)  $<  /usr/local/lib/libboost_chrono.a  -o $@  $(LIB_DIRs) $(LIB_NMs)

I have used both techniques, I find the first easier. 我已经使用了两种技术,但我发现第一种更容易。

Note that archive code might refer to symbols in another archive. 请注意,存档代码可能引用另一个存档中的符号。 You can command the linker to search a library multiple times. 您可以命令链接程序多次搜索库。

If you let the build link with the .so, this does not pull in a copy of the entire .so into the build. 如果让构建与.so链接,则不会将整个.so的副本拉入构建。 Instead, the .so (the entire lib) is loaded into memory (if not already there) at run-time, after the program starts. 而是在程序启动后,在运行时将.so(整个lib)加载到内存中(如果尚未存在)。 For most applications, this is considered a 'small' start-up performance hit as the program adjusts its memory map (auto-magically behind the scenes) Note that the app itself can control when to load the .so, called dynamic library. 对于大多数应用程序,由于程序会调整其内存映射(在后台自动魔术),因此这被认为对启动性能造成了“小影响”。请注意,应用程序本身可以控制何时加载.so(称为动态库)。


Unrelated: 无关:

// If your C++ 'Hello World' has no class ... why bother?
#include <iostream>

class Hello_t {
public:
   Hello_t()  { std::cout << "\n  Hello"  << std::flush; }
   ~Hello_t() { std::cout <<    "World!" << std::endl; }
   void operator() () { std::cout << " C++ "; }
};
int main(int, char**) { Hello_t()(); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM