c++ - 共享库的静态库中静态变量的单独实例

标签 c++ linux shared-libraries clang static-libraries

考虑以下由两个共享库组成的设置,它们都使用静态库:

static.cpp

#include "static.h"
static int a = 0;
int getA()
{
    return a++;
}

static.h

#pragma once
int getA();

shareda.cpp

#include <iostream>
#include "shareda.h"
#include "static.h"
void printA()
{
    std::cout << getA() << std::endl;
}

shareda.h

#pragma once
void printA();

sharedb.cpp

#include <iostream>
#include "sharedb.h"
#include "static.h"
void printB()
{
    std::cout << getA() << std::endl;
}

sharedb.h

#pragma once
void printB();

main.cpp

#include "shareda.h"
#include "sharedb.h"
int main()
{
    printA();
    printA();
    printB();
    printA();
    printB();
    return 0;
}

我使用以下命令编译并运行了这些文件(使用从源代码编译的 Clang 3.8.0 和带有 GNU ld 2.25 的 64 位 Debian):

clang++ -c static.cpp -o static.o -fPIC
ar rcs libstatic.a static.o
clang++ -c shareda.cpp -o shareda.o -fPIC
clang++ -shared -o libshareda.so shareda.o libstatic.a
clang++ -c sharedb.cpp -o sharedb.o -fPIC
clang++ -shared -o libsharedb.so sharedb.o libstatic.a
clang++  -L. -lshareda -lsharedb -o main main.cpp
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main

令我惊讶的是,输出如下:

0
1
2
3
4

我的期望是这样的:

0
1
0
2
1

显然,尽管在 static.cpp 中 a 前面有 static 关键字,但只有一个 a 实例存在。有没有办法让 a 的两个实例,每个共享库一个?

最佳答案

Apparently, despite the static keyword in front of a in static.cpp, only one instance of a exists.

那是不正确:a 存在两个实例,但实际只使用了一个。

之所以发生,是因为(与您的预期相反)printB 调用了第一个 getA 可用(来自 libshareda.so 的那个,而不是来自 libsharedb.so 的那个)。这是 UNIX 共享库和 Windows DLL 之间的一个主要区别。 UNIX 共享库模拟如果您的链接是:

clang++  -L. -o main main.cpp shareda.o sharedb.o libstatic.a

那么你能做些什么来“解决”这个问题呢?

  1. 您可以使用 -Bsymbolic 链接 libsharedb.so 以更喜欢它自己的 getA
  2. 您可以将 getA 完全隐藏在 libsharedb.so 中(就像它是私有(private)实现细节一样):

    clang++ -c -fvisibility=hidden -fPIC static.cpp ar rcs libstatic.a static.o clang++ -shared -o libsharedb.so sharedb.o libstatic.a

  3. 您可以使用链接器版本脚本获得类似的结果。

附言您的链接命令:

clang++  -L. -lshareda -lsharedb -o main main.cpp

完全倒退。应该是:

clang++  -L. -o main main.cpp -lshareda -lsharedb

源/目标文件和库在命令行上的顺序 matters ,并且库应该遵循引用它们的目标文件。

关于c++ - 共享库的静态库中静态变量的单独实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34381562/

相关文章:

c++ - 有没有办法反编译 Linux .so?

c - 当 `GC.enable(true)` 时,在 Julia 中使用 ccall 时出现段错误

c++ - POSIX 扩展正则表达式 - 不包含 X 但包含 Y (std::regex c++11)

C++ 调用类成员变量 "attributes"是否正确?

linux - 比较Linux中多个文件的文件名和md5sums

java - UnknownHostException 访问 virtualBox 上的服务

linux - 共享库怎么可能定义一个函数但不能链接到它?

c# - 使用 Chromium Embedded 有没有办法从 Javascript 与程序通信?

c++ - 多个构造函数的内存使用c++

ruby - 找不到 gem 命令