C++ 静态库中的共享全局变量:Linux

Posted

技术标签:

【中文标题】C++ 静态库中的共享全局变量:Linux【英文标题】:Shared global variable in C++ static library: Linux 【发布时间】:2016-09-30 20:21:14 【问题描述】:

这在 C++ 中:

静态库“A”定义了一个全局变量 foo。

“B”和“C”是两个动态库,都依赖于 A,因此(静态)与 A 链接。

然后 B 和 C 最终在同一个进程中加载 (例如:应用程序加载 B 和 C)。

如果我们在windows环境中,我们将获得两个不同的foo实例,一个在B中,一个在C中,如下所示:

Shared global variable in C++ static library

Linux 环境怎么样。

上下文: 我们目前正在将一个 windows 项目移植到 linux

【问题讨论】:

如果您没有得到答案,我想您可以通过更改第一个库中的全局变量并检查第二个库中的值来执行一个简单的测试。 【参考方案1】:

每个库都将包含 A 的副本。但是,在运行时,进程的所有组件只会使用一个。

// h.h
extern int a;
void b(void);
void c(void);

// a.c
#include "h.h"
int a = 0;

// b.c
#include <stdio.h>
#include "h.h"
void b(void)

  printf("%i\n", a++);


// c.c
#include <stdio.h>
#include "h.h"
void c(void)

  printf("%i\n", a++);


//main.c
#include <stdio.h>
#include "h.h"
int main()

  b();
  c();


#Makefile
main: libxc.so libxb.so
    cc -o main main.c -L. -lxc -lxb
libxb.so:
    cc -fPIC -shared a.c b.c -o libxb.so
libxc.so:
    cc -fPIC -shared a.c c.c -o libxc.so
$make
$ LD_LIBRARY_PATH=。 。/主要的
0
1

来自libxa.so的符号表:

53: 000000000020098c 4 对象全局默认值 24 a

来自libxc.so

53: 000000000020098c 4 对象全局默认值 24 a

默认可见性为STV_DEFAULT,根据LSB:

STV_DEFAULT:符号的可见性与STV_DEFAULT 属性由符号的绑定类型指定。那是, 全局和弱符号在其外部可见 定义 组件(可执行文件或共享对象)。本地符号是 隐藏,如下所述。全局和弱符号也是 可抢占的,也就是说,它们可以被相同的定义抢占 在另一个组件中命名。

man 5 elf:

STV_DEFAULT:默认符号可见性规则。 Globa 和weak 符号可供其他人使用 模块;本地模块中的引用可以 被其他定义插入 模块。

关于SysV ABI:

解析符号引用时, 动态链接器使用广度优先搜索检查符号表。 也就是先看可执行文件的符号表 程序本身,然后在符号表 DT_NEEDED 条目(按顺序),然​​后在第二级 DT_NEEDED 条目,等等。

如果这不是预期的,在符号上使用STV_HIDDEN 可以防止它在共享对象之外可见。

相比之下,在 Windows 上,符号总是从给定的 DLL 导入,并且默认情况下不会将符号导出到其他 DLL。

【讨论】:

以上是关于C++ 静态库中的共享全局变量:Linux的主要内容,如果未能解决你的问题,请参考以下文章

Solaris 共享库和全局变量

在 C 代码库中查找全局/静态变量的工具

如何在运行时确定共享库中全局变量的地址范围?

C++中的全局变量普通局部变量和静态局部变量的区别

不同的静态全局变量共享相同的内存地址

C++中的静态全局变量