【问题标题】:Single copy of global variables in Linux shared libraryLinux 共享库中全局变量的单一副本
【发布时间】:2013-08-21 15:40:48
【问题描述】:

这个问题与this one 非常相似,但是其中提到的解决方案都没有帮助。

假设我有一个共享库 B,其中包含一个使用局部全局变量的函数。这个函数是从第二个共享库 C 中调用的。

B 和 C 都被 A 使用,我希望每个都有自己的全局变量实例,但编译器设法将它们链接到同一个对象(与 Windows 不同)。

有人可以建议一种方法来允许我在 A 中使用不同的全局变量实例吗?

下面是我的代码。 运行 a.out 时,我希望得到

1
calling from someCFunc(): 1

但是,我得到:

1
calling from someCFunc(): 2

b.h:

#ifndef _B_H_
#define _B_H_

extern "C" __attribute__ ((visibility("default"))) void myFunc();

#endif

b.cpp:

#include "b.h"
#include <iostream>

int myGlobal = 0;

extern "C" __attribute__ ((visibility("default"))) void myFunc()
{
    ++myGlobal;
    std::cout << myGlobal << "\r\n";
}

c.h:

#ifndef _C_H_
#define _C_H_

extern "C" __attribute__ ((visibility("default"))) void someCFunc();

#endif

c.cpp

#include "c.h"
#include "b.h"
#include <iostream>

extern "C" __attribute__ ((visibility("default"))) void someCFunc()
{
    std::cout << "calling from someCFunc(): ";
    myFunc();
}

a.cpp:

#include "b.h"
#include "c.h"

int main(void)
{
    myFunc();
    someCFunc();

    return 0;
}

构建脚本:

rm *.so
rm *.out
g++ -fPIC -fvisibility=hidden -shared b.cpp -o libb.so
g++ -fPIC -fvisibility=hidden -shared b.cpp -o libb2.so
g++ -fPIC -fvisibility=hidden -shared c.cpp -o libc.so -l:libb.so
g++ a.cpp -fPIC -fvisibility=hidden -l:libb2.so -l:libc.so

【问题讨论】:

  • c.cpp的来源是什么?
  • @bennofs - 添加源

标签: c++ linux gcc g++ shared-libraries


【解决方案1】:

B 和 C 都被 A 使用,我希望每个都有自己的全局变量实例

你的期望是错误的。您在这里观察到的是正确和预期的行为。如果您的期望是真的,那么每个单独的库都会面临与臭名昭著的钻石类层次结构非常相似的问题。

有人可以建议一种方法来允许我在 A 中使用不同的全局变量实例吗?

据我所知,这在 C++ 中是不可能的。如果你想使用不同的变量,你必须分别定义它们并传递一个对你的函数的引用:

// B
void myFunc(int& myVar) {
    ++myVar;
    std::cout << myVar << "\r\n";
}

// C
int myGlobalC = 0;
void someCFunc() {
    myFunc(myGlobalC);
}

// A
int myGlobalA = 0;
int main() {
    myFunc(myGlobalA);
    someCFunc();
}

【讨论】:

  • 这是可能的,因为当我在 VS2010 上运行代码时确实得到了预期的结果(将 attribute... 更改为 __declspec(dllexport))...必须是一种在 linux 中模仿相同行为的方法
  • 详细说明:从 A 的角度来看,它使用了两个不同的库,称为 b2 和 c。它不(也不应该)期望他们的行为以任何方式联系起来。假设 b2 是从一个不同的源代码(foo.cpp,foo.h)构建的,它恰好有一个名为 myGlobal 的全局整数,为什么要将它链接到另一个名为 c 的库使用的变量??!??跨度>
  • @MarkS 我的错,我不知何故忽略了一个事实,即您有两个相同的库以不同的名称命名。长话短说:恐怕你不能在 Linux 上执行此操作,因为运行时链接器(库加载器)处理符号的方式与 Windows 不同。冲突的符号将被最新加载的库“覆盖”。我现在没有时间详细回答,但我会尽快整理。也许dlopen 可以提供帮助,但这是一种黑客攻击。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-14
  • 2013-06-12
相关资源
最近更新 更多