2013-08-21 57 views
2

這個問題與this one非常相似,但是沒有提到的解決方案有幫助。Linux共享庫中全局變量的單個副本

假設我有一個共享庫B,其中包含一個使用本地全局變量的函數。從第二個共享庫C調用此函數。

A和B都使用B和C,我期望每個都有自己的全局變量實例,但不知何故編譯器設法將它們鏈接到指向同一個對象(不像Windows)。

有人可以提出一種方法,讓我有不同的A全局變量的實例嗎?

以下是我的代碼。 當運行a.out的,我希望得到

1 
calling from someCFunc(): 1 

不過,我得到:

1 
calling from someCFunc(): 2 

BH:

#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"; 
} 

ch:

#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; 
} 

buildscript:

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 
+0

c.cpp的來源是什麼? – bennofs

+0

@bennofs - source added –

回答

1

B和C由A使用,我會期望每個人都擁有自己的全局變量實例e

你的期望是錯誤的。你在這裏觀察的是正確和預期的行爲。如果你所期望的是真實的,那麼在那裏的每一個圖書館都將面臨一個與臭名昭着的鑽石級別相似的問題。

有人可以提出一種方法,讓我有不同的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(); 
} 
+0

這是可能的,因爲我在VS2010上運行代碼時發生了預期的結果(將__attribute __...更改爲__declspec(dllexport))...必須有一種方法來模擬相同的在linux中的行爲 –

+0

只是爲了闡述:從A的角度來看,它使用了兩個不同的庫,分別叫做b2和c。它不會(也不應該)期望他們的行爲以任何方式被鏈接。假設b2是由不同的源代碼構建的(foo.cpp,foo。h)碰巧有一個名爲myGlobal的全局整數,爲什麼它應該鏈接到另一個名爲c?的庫所使用的變量! –

+0

@MarkS我不好意思,我忽略了一個事實,即你有兩個完全相同的命名庫。長話短說:恐怕你不能在Linux上這樣做,因爲運行時鏈接程序(庫加載程序)不像Windows那樣處理符號。衝突的符號將被最新加載的庫「覆蓋」。我現在沒有時間做詳細的答案,但我會盡快將它們放在一起。也許'dlopen'可以幫助,但這是一種破解。 – syam

相關問題