繁体   English   中英

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

[英]static and dynamic linking using gcc

我最近一直在阅读有关静态和动态链接的信息,我了解它们之间的区别以及如何创建静态和动态库并将其链接到我的项目

但是,我想到一个问题,我无法回答或找到答案,因为这是一个特定的问题……当我使用以下代码在linux上编译代码时

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

使用此命令进行编译

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

这是哪种链接? 所以stdio.h是静态或动态链接到我的项目的???

库主要用作共享资源,因此几个不同的程序可以以某种方式重用相同的预编译代码。 一些库作为标准库提供,它们随操作系统和/或编译器软件包一起提供。 一些图书馆还带有其他第三方项目。

当以示例方式仅运行gcc时,实际上就是在运行一个编译器驱动程序,该驱动程序为您提供了一些与编译相关的功能,调用了编译过程的不同部分,最后将您的应用程序与一些标准库链接在一起。 库的类型是根据您提供的限定符选择的。 默认情况下,它将尝试查找动态(共享)库,如果缺少,将尝试使用静态库。 除非您告诉它仅使用静态库(-static)。

当您链接到项目库时,您告诉gcc / g ++使用哪种库(-lname)。 这样,它将与标准库相同,除非使用-static,否则首先查找“ .so”,然后查找“ .a”。 您也可以直接指定完整库名的路径,实际上告诉它要使用哪个库。 还有其他几个限定链接过程的限定符,请在man中查找'g ++'和'ld'。

库必须包含真实的程序代码和数据。 它链接到主要可执行文件(和其他库)的方式是通过符号表(它们是库的一部分)进行的。 符号表包含用于全局函数的数据条目。

共享库和静态库的结构略有不同。 前一个实际上是一个预链接的对象,类似于一个可执行映像,带有一些与符号和重定位有关的额外信息(此类库可以加载到内存中的任何地址,并且仍然可以正常工作)。 静态库实际上是'.o'文件的存档,可以进行完整的链接。

创建库的通常步骤是将程序的多个部分编译为“ .o”文件,这些文件又可以通过“ ld”(或g ++)链接到共享库中,或通过“ ar”存储在.a中。 之后,您可以使用它们以上述方式进行链接。

每个.cpp源文件创建一个目标文件(.o)。 源文件包含代码,并且可以包含任意数量的头文件,在您的情况下(或cstdio)为“ stdio.h”或类似名称。 这些文件成为由cpp预处理程序保障的源文件的一部分。 后者负责宏并展平所有#include层次结构,以便编译器仅看到单个文本流,并将其转换为“ .o”。 通常,头文件不应包含可执行代码,而应包含声明和宏,尽管并非总是如此。 但这并不重要,因为它们已与主源文件融合在一起。

希望这能解释它。

这是哪种链接? 所以stdio.h是静态或动态链接到我的项目的???

stdio.h未链接,它是头文件,并且包含代码/文本,没有编译的对象。

当两个链接都位于同一目录中时,普通链接过程相对于“ .a”存档更喜欢使用“ .so”库。 您的简单命令是与.so(如果在正确的路径中)或.a(如果在没有.so等效项的路径中找到)链接。

要实现静态链接,您有几种选择,包括

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)

我已经使用了两种技术,但我发现第一种更容易。

请注意,存档代码可能引用另一个存档中的符号。 您可以命令链接程序多次搜索库。

如果让构建与.so链接,则不会将整个.so的副本拉入构建。 而是在程序启动后,在运行时将.so(整个lib)加载到内存中(如果尚未存在)。 对于大多数应用程序,由于程序会调整其内存映射(在后台自动魔术),因此这被认为对启动性能造成了“小影响”。请注意,应用程序本身可以控制何时加载.so(称为动态库)。


无关:

// 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