当库静态链接时,静态变量会发生什么情况

What happens to static variables when libraries are statically linked

本文关键字:静态 变量 什么情况 链接      更新时间:2023-10-16

假设我有实现单例模式(A)库(它的实现中有一个静态变量)。

(A)库被编译为静态库。

现在,假设我的 probject 中有:

  • (B),另一个静态库与(A)静态链接。
  • (C),另一个静态库与(A)静态链接。
  • (D),一个与(B)(C)链接的顶级程序。

最后,我的单例真的是单例吗(我的变量真的是静态的)?(B)(C)是否从(A)中获取相同的静态变量(它是 unic)?还是(A)被静态链接两次的事实嵌入了两次(A)的代码,最终我的静态变量(A)在最终的二进制代码中出现两次?那么,如果(B)修改静态变量值,(C)看不到变化?

注意:在将项目的库更改为静态链接而不是动态链接时,我遇到了这种情况。我只是想知道我是否做错了什么,或者这是否是一种正常的已知行为。

首先:

(B) 和 (C) 不与 (A) 链接。静态库是编译的,而不是链接的。在构建 (B) 和 (C) 时,编译器可能需要查看 (A) 中的某些定义,但不要将其与链接混淆。(A)代码不会复制到(B)或(C)中。

其次:

(D) 必须与 (A)、(B) 和 (C) 链接。这意味着您只会获得 (D) 中 (A) 代码的一个副本。

动态链接库/共享对象:

当然,如果(B)和(C)是dll/sos,情况会有所不同。Dll 是链接的,因此,如果您将 (B) 和 (C) 构建为 dll 并将它们与 (A) 链接,那么您将在 (B) 和 (C) 中拥有 (A) 代码的单独副本。

(B) 和 (C) 是否从 (A) 中获取相同的静态变量

这取决于变量是具有外部链接还是内部链接。以下头文件包含一个具有内部链接的静态 int 变量。这意味着包含此文件的每个翻译单元都将获得自己的myVariable副本。

//MyHeader.h
#pragma once
static int myVariable = 0;

静态链接库,和静态变量不相关。

静态变量在当前编译范围之外不可见(在 .o 文件中不会创建符号名称,因此没有其他 .o 文件可以通过符号名称找到该变量)。

这意味着变量

static int foo;可以存在于每个编译范围中,并且每个范围都是Uniqe

你的静态变量实际上是静态的。我怀疑即使(B)链接(A),(B)没有选择它自己的(A)副本 - 相反,它包含(A)应该链接的信息。

但是,可以在两个库中使用静态变量编译相同的源代码 - 例如:

测试.cpp:

int g_myGlobal = 23;

并在 (A) 和 (B) 静态库中编译它,但是当链接整个应用程序或 dll 时 - 您将收到有关双重定义静态变量的链接器错误。

但是,如果使用静态关键字声明变量:

测试.cpp:

static int g_myGlobal = 23;

然后,如果从 (A) 和 (B) 链接相同的源代码 - 它将被编译和链接正常,但结果您将有两个g_myGlobal变量实例(甚至可能不同)。