[MinGW cross-compiling] Lokale statische Variablen in DLL und Hauptprogramm
-
Ich versuche mit MinGW unter Linux für Windows "cross zu kompilieren".
Folgender Code:
common.h:
class common { public: static void set (int val) { get () = val; } static int& get () { static int val; return val; } };
main.cpp:
#include <stdio.h> #include "common.h" void dllFunc (); int main () { common::set (3); printf ("From application: %d\n", common::get ()); dllFunc (); return 0; }
dll.cpp:
#include <stdio.h> #include "common.h" void dllFunc () { printf ("From DLL: %d\n", common::get ()); }
dll.cpp wird als DLL gelinkt und wird zu
dll.dll
.
main.cpp wird als EXE gelinkt und wird zumain.exe
.Die Ausgabe sieht (fälschlicherweise) wie folgt aus:
From application: 3
From DLL: 0(Unter wine sowie unter dem "echten" Windows.)
Wenn ich dll.cpp und main.cpp direkt zusammenlinke, so dass keine DLL verwendet wird, bekomme ich (korrekterweise):
From application: 3
From DLL: 3Ebenso, wenn ich nativ mit g++ kompiliere und linke.
Ich vermute mal, dass das ein Windows-spezifisches "Problem" ist, welches dafür sorgt, dass lokale statische Variablen in jedem "Modul" eine eigene Instanz bekommen? Wie kann ich das vermeiden, so dass jedes Modul auf die selbe Instanz zugreift?
-
Hab von DLLs nicht gerade viel Ahnung
Aber warum nutzt du Klassen und C-Header und nicht die C++-Header?
Das kann dir Fehler produzieren!
Bei aktuelle Quelltexten gilt:
C-Header zu C und
C++-Header zu C++Bei C++ sollte sowas in deinem Quelltext sein:
#ifdef __cplusplus extern "C" { #endif
Bei pur C mögen das einige Compiler nicht!
Und die Beispiele, die ich kenne hätten gern einen:
#include <windows.h>
Aber die Jungs, die C/C++ vor ihrer Muttersprache konnten melden
sich wahrscheinlich nochMfG f.-th.
-
devkid schrieb:
Ich vermute mal, dass das ein Windows-spezifisches "Problem" ist, welches dafür sorgt, dass lokale statische Variablen in jedem "Modul" eine eigene Instanz bekommen? Wie kann ich das vermeiden, so dass jedes Modul auf die selbe Instanz zugreift?
Etwas, das "static" deklariert ist, egal ob global oder lokal, ist in jedem einzelnen "Modul" (compilation unit) einmal vorhanden, nicht nur unter Windows.
Damit mehrere Compilation units die selbe Variable verwenden, muss sie External Linkage haben, so dass der Linker beim Linken der einzelnen Compilation Units Zugriffe darauf auf die selbe Speicherstelle zusammenführt. Aber das geht nicht für lokale Variablen. Zumindest nicht in C.
-
namespace invader schrieb:
Etwas, das "static" deklariert ist, egal ob global oder lokal, ist in jedem einzelnen "Modul" (compilation unit) einmal vorhanden, nicht nur unter Windows.
Ich behaupte einfach mal das Gegenteil und sage, dass der oben aufgeführte Quelltext als
main.bin
undlibdll.so
nativ mit g++ kompiliert, die zweite Version ausspuckt, sprich: Das gesamte Programm hat nur eine Instanz der Variable.
Und es ist eben nicht egal, ob die statische Variable global oder lokal ist. Wenn sie global definiert ist, dann enthält jede "Compilation unit" (bei mir sind das .o's), die beispielsweise den Header, der sie definiert, einbindet, eine eigene Instanz dieser Variable. static bei lokalen Variablen hat nur den Effekt, dass die Variable nur beim ersten Funktionsaufruf belegt wird, nicht freigegeben wird, wenn der Funktionskörper verlassen wird, und bei jedem weiteren Aufruf auf den Speicher verweist, der beim ersten Mal angefordert wurde.@f.-th.: Meinst du .h/.hpp? Ich kompilieren eine .cpp-Datei und der Kompiler weiß, dass alles, was ich #include' auch C++ ist.
-
devkid schrieb:
static bei lokalen Variablen hat nur den Effekt, dass die Variable nur beim ersten Funktionsaufruf belegt wird, nicht freigegeben wird, wenn der Funktionskörper verlassen wird, und bei jedem weiteren Aufruf auf den Speicher verweist, der beim ersten Mal angefordert wurde.
Nein, auch eine lokale static-Variable wird schon vor Programmstart initialisiert; deswegen muss zum Initialisieren auch ein konstanter Ausdruck verwendet werden, während "normale" lokale Variablen auch z.B. mit einem Funktionsparameter initialisiert werden können. Für Speicherung und Lebensdauer macht es bei static-Variablen keinen Unterschied, ob sie global oder lokal deklariert werden.
-
namespace invader schrieb:
Nein, auch eine lokale static-Variable wird schon vor Programmstart initialisiert; deswegen muss zum Initialisieren auch ein konstanter Ausdruck verwendet werden, während "normale" lokale Variablen auch z.B. mit einem Funktionsparameter initialisiert werden können. Für Speicherung und Lebensdauer macht es bei static-Variablen keinen Unterschied, ob sie global oder lokal deklariert werden.
Nein. Drei mal falsch:
#include <stdio.h> class ABC { public: ABC () { printf ("Hi, there!\n"); } }; int func (int abc) { static int val = abc; return 0; } int abc () { static ABC inst; return 0; } int main () { printf ("OK!\n"); func (123); abc (); return 0; }
Ausgabe:
OK!
Hi, there!1. Eine lokale statische Variable wird nicht beim Programmstart initialisiert (
ABC::ABC ()
gibt seinen Text erst nach "OK!" aus).
2. Ich kann eine lokale statische Variable mit einem Parameter initialisieren (siehefunc ()
).
3. Die Lebenszeit einer lokalen statische Variablen beginnt beim ersten Aufruf der Funktion, die sie definiert.
-
Nagut, dann ist es wohl eine C++-Eigenheit. In C werden Objekte mit Static Storage Duration (also welche mit internal oder external Linkage und welche, die mit 'static' deklariert wurden) auf jeden Fall vor Programmstart inititialisiert, und die Initializer müssen konstante Ausdrücke sein. Deine Funktion func() geht in C so nicht.
(Achso, und sehe gerade, dass (zumindest in C) eine lokale (block scope) Variable doch External Linkage haben kann, nämlich wenn man sie mit 'extern' deklariert)
-
Naja, hab das ganze jetzt einfach mit einer statischen Klassen-Variable gelöst. Ist zwar aufwändiger, aber läuft wenigstens... (auf Windows...).