2011-02-07 4 views
5

* Pytanie zmieniony (patrz poniżej) *zmienna globalna ma wiele kopii w systemie Windows i Linux na pojedynczym gdy skompilowany zarówno Exec i wspólne libaray

Mam plik cpp, który definiuje zmienną statyczną np globalnego

Ten plik cpp jest kompilowany do pliku wykonywalnego i biblioteki współużytkowanej. Plik wykonywalny może załadować bibliotekę współdzieloną w czasie wykonywania.

Jeśli jestem na Linuksie, wydaje się, że są dwie kopie tej zmiennej. Zakładam, że jeden pochodzi z pliku wykonywalnego, a drugi z biblioteki współdzielonej. Inne platformy (HP, Windows) wydają się mieć tylko jedną kopię.

Co kontroluje to zachowanie w systemie Linux i czy mogę to zmienić? Na przykład czy istnieje flaga kompilatora lub linkera, która wymusi wersję tej zmiennej z biblioteki współdzielonej na taką samą, jak wersja pliku wykonywalnego?

* Przegląd pytanie *

Dzięki za odpowiedzi tak daleko. Po ponownym zbadaniu problemu nie jest to problem opisany powyżej. Statyczna zmienna globalna powyżej rzeczywiście ma wiele kopii w systemie Windows, więc nie ma różnicy od tego, co widzę w systemie Linux.

Jednak, Mam inną zmienną globalną (nie statyczną tym razem), która jest zadeklarowana w pliku cpp i jako plik zewnętrzny w pliku nagłówkowym.

W systemie Windows ta zmienna ma wiele kopii, jedną w pliku wykonywalnym i jedną w każdej załadowanej bibliotece dll, a na Linuksie ma tylko jedną. Więc teraz pytanie dotyczy tej różnicy. Jak mogę sprawić, by Linux miał wiele kopii?

(Logika mojego programu oznaczało, że wartość zmiennej statycznej globalnej była zależna od wartości zmiennej non-statycznej globalnej i zacząłem zarzucając niewłaściwą zmienną jako problem)

Odpowiedz

4

Sugeruję przeczytanie following. Później zrozumiesz wszystko o bibliotekach współdzielonych w Linuksie. Jak powiedzieli inni, szybka odpowiedź brzmi, że słowo kluczowe static ograniczy zakres zmiennej globalnej do jednostki tłumaczeniowej (a tym samym do biblioteki wykonywalnej lub współdzielonej). Użycie słowa kluczowego extern w nagłówku i skompilowanie cpp zawierającego tę samą zmienną globalną tylko w jednym z modułów (exe lub dll/so) spowoduje, że zmienna globalna będzie unikalna i współdzielona przez wszystkie moduły.

EDIT: zachowanie w systemie Windows nie jest taka sama jak w Linuksie podczas korzystania z wzoru extern ponieważ metoda Windows', aby załadować bibliotek dynamicznych (DLL) nie jest taka sama i jest zasadniczo niezdolna powiązanie zmiennych globalnych dynamicznie (tak, że tylko jeden istnieje). Jeśli można użyć statycznego obciążenia DLL (nie używając LoadLibrary), a następnie można użyć następujących:

//In one module which has the actual global variable: 
__declspec(dllexport) myClass myGlobalObject; 
//In all other modules: 
__declspec(dllimport) myClass myGlobalObject; 

To sprawi, że myGlobalObject wyjątkowy i dzielone pomiędzy wszystkich modułów, które korzystają z biblioteki DLL, w którym pierwszy wersja powyższego jest używana.

Jeśli chcesz, aby każdy moduł miał własną instancję zmiennej globalnej, użyj słowa kluczowego static, zachowanie będzie takie samo dla systemu Linux lub Windows.

Jeśli chcesz jedną unikalną instancję zmiennej globalnej ORAZ wymagać ładowania dynamicznego (LoadLibrary lub dlopen), musisz wykonać funkcję inicjalizacji, aby każdy załadowany plik DLL zawierał wskaźnik do zmiennej globalnej (zanim zostanie użyty) . Będziesz musiał również zachować licznik odwołań (możesz użyć do tego celu shared_ptr), abyś mógł utworzyć nowy, gdy żaden nie istnieje, zwiększyć licznik w inny sposób i być w stanie go usunąć, gdy liczba zostanie ustawiona na zero, ponieważ pliki DLL są rozładowywany.

+0

Działanie systemu Windows zostało podane niepoprawnie. Zobacz poprawione pytanie o rzeczywistą różnicę między Windows i Linux. – Reuben

+0

Zobacz moją zaktualizowaną odpowiedź. Ponadto przeczytanie artykułu, do którego się przyłączyłem, wyjaśni, dlaczego Linux jest w stanie to osiągnąć i dlaczego jest trudne i najwyraźniej niemożliwe w systemie Windows. –

+0

Odpowiedź znalazła się w sekcji 2.2 dokumentu związanego z linkami. Z powodu starszej wersji kompilatora, do której byłem ograniczony i mogłem zmienić źródło, w którym zadeklarowano zmienną, skończyłem używając map eksportu (sekcja 2.2.5) – Reuben

1

Co kompilator prawda używać na każdej z tych platform? Zachowanie, które opisujesz dla Linuksa, byłoby tym, czego oczekiwałbym, statyczny globalny jest tylko lokalny dla tego konkretnego pliku podczas kompilacji.

+0

Zachowanie Windows został podany niepoprawnie. Zobacz poprawione pytanie o rzeczywistą różnicę między Windows i Linux. Kompilator Windows to MS Visual Studio 2003 Linux to gcc 3.3.3 HP to aC++/ANSI C B3910B A.06.01 [Jan 05 2005] – Reuben

+0

@Reuben: To są bardzo stare kompilatory, powinieneś rozważyć aktualizację dla obu platform . Nie sądzę jednak, żeby to zmieniło zachowanie. –

0

Nie wiem o HPUX, ale w systemie Windows, jeśli masz plik EXE i DLL, i każdy z nich deklaruje zmienne globalne, wtedy będą dwie różne zmienne. Jeśli otrzymujesz tylko jedną zmienną, jeden obraz musi importować zmienną z drugiej.

3

Kwalifikator static zastosowany do zmiennej przestrzeni nazw oznacza, że ​​zakresem zmiennej jest jednostka tłumaczeniowa. Oznacza to, że jeśli ta zmienna jest zdefiniowana w nagłówku, a Ty ją umieścisz z wielu plików .cpp, otrzymasz kopię dla każdego z nich. Jeśli chcesz mieć jedną kopię, oznacz ją jako extern (a nie static) w nagłówku, zdefiniuj w pojedynczej jednostce tłumaczeniowej i połącz ją w pliku wykonywalnym lub bibliotece (ale nie w obu).

Powiązane problemy