Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Globale Variablen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
02.05.2006, 11:33 Uhr
~Starbuck
Gast


Hallo zusammen,

ich hab mal eine spezielle Frage zu globalen Variablen:

Die Lehrbücher sagen natürlich, dass man sie vermeiden sollte und ich hab das eigentlich auch immer getan. Nun bin ich in einer Situation, wo ich es nur mehr bedingt vermeiden kann:

ich schreibe eine DLL, die an eine oder mehrere andere DLLs gebunden wird. Dabei hab ich aber absolut keinen Einfluss auf den Source Code der anderen DLLs. Es gibt nur Zugriffe über Callbacks auf Daten, die in den externen DLLs gespeichert sind.

Nun hab ich selbst mehrere Sourcecode Files in denen sich mehrere Funktionen befinden. Ein beträchtlicher Teil der Daten muss nun in teilweise sehr vielen dieser Funktionen bekannt sein und ich kann sie nicht immer als Parameter übergeben. Es gibt jedoch eine Möglichkeit, über Callbacks Werte (leider nur 32 Bit unsigned Werte) in externe DLLs zu schreiben und sie von dort wieder zu lesen. Diese Callbacks sind natürlich "global" und können auch überall aufgerufen werden. So kann ich mir "meine" globalen Variablen dann sparen.

Jedoch ist das halt sehr umständlich und benötigt im Vergleich zu globalen Variablen sehr viel Laufzeit, die bei Simulationen schon kritisch werden kann.

Ich würde gern ein paar Meinungen dazu hören, was hier "besser" ist.

Vielen Dank auf jeden Fall schon mal im voraus.

LG

Starbuck
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
02.05.2006, 11:41 Uhr
kronos
Quotenfisch
(Operator)


Du kannst Datenstrukturen verwenden um mehrere Variablen auf einmal zu übergeben, also structs, in C++ natürlich auch Klassen.
--
main($)??<-$<='?'>>2?main($-!!putchar(
(("$;99M?GD??(??/x0d??/a:???;a"+'?'/4)
??($??)+'?'/3-2-1+$%2)??''?')):'?';??>
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
02.05.2006, 12:25 Uhr
RHBaum



vermeiden und verhindern iss schon nen unterschied ^^
"Globale variablen" wird man hin und wieder brauchen, die Kunst iss nur sie Salonfaehig zu machen ...
Unter C hasst da eh keine chance ^^ Ok da sind globale variablen eh geduldet. ...

Unter C++ heisst das Mittel zum Zweck meist statische membervariable ...

Das ist die Theorie ....
Was ich nicht ganz verstehe, iss was du wirklich brauchst ...

Globale variablen nimmt man, nicht wegen deren Inhalt, da kann wie in jeder variable alles drinne stehen, sondern wegen Ihren Scope und ihren Lebenszyklus.
Sprich eine globale variable in ner Dll wird erzeugt, wenn eine Instanz deiner Dll angezogen wird (die Exe gestartet) bzw, wenn irgendwer zum ersten mal auf die globale Variable zugreift ....
Alle internen und externen (exportierten) funktion der DLL haben dann zugriff auf diese Varaible.

Eine Instanz der DLL (kopie aller globalen Daten) wird fuer jeden prozess erstellt, der die Dll nutzt.
Sprich in einem Prozess kannst du X mal LoadLibrary auf deine dll aufrufen wie du willst, beim ersten mal wird ne Instanz erzeugt, beim zweiten mal bekommst nur nen Handle (HInstance) auf deine schon instanzieierte DLL zurueck.

rufen 2 unterschiedliche Prozesse (2 unterschiedliche exe's oder eine mit CreateProzess (die windows version von fork) erzeuge Abspaltung ) die Dll auf, werden 2 unterschiedliche Instanzen erzeugt .... sonst waere IPC ja auch zu einfach ^^


Zitat:

Es gibt nur Zugriffe über Callbacks auf Daten, die in den externen DLLs gespeichert sind.


Meinst du hier wirklich callbacks ???
Callbacks sind grundsaetzlich gesehen .... von der externen Komponente definierte Funktionsaufrufe, die du implementieren musst, und bei einem anderen funktionsaufruf von dir zur externen Dll musst du dann nen zeiger auf deine implementation mitgeben .
Innerhalb der abarbeitung der 1. Aufruffunktion ruft die externe Dll dann bei bedarf deinen Callback auf !
Callbacks - Rueckruffunktionen werden unter C eigentlich fuer nur 3 anwendungsfaelle verwendet :
Du bist fuer die externe Dll die Unbekannte:
- die externe Dll will dir X-mal (dynamisch) Daten geben, ohne eine grosse dynamische struktur erst im Speicher aufbauen zu muessen ... sie ruft einfach X mal dein Callback auf ... mit ner simplen statischen Datenstruktur ...
- die externe Dll will dynamisch von dir noch Daten, die sie braucht, um diese daten zu bekommen ruft sie Callbacks auf mit Datenstrukturen, die du in deiner Impl befuellen musst ...
- sie informiert dich ueber Ereignisse waehrend einer komplexen Funktion (Schnittstelle progressAnzeige als Beispiel) oder sie will dir zeit geben um auf usereingaben zu reagieren, so das dein Programm keine 2h deine GUI blockiert(vermeidung von multithreading)

Da Dlls und die aufrufende Exe sich den Datenbereich teilen ... isses kein Problem komplexe strukturen zu uebergeben ... einfach mittels zeiger drauf. Problem ist nur wenn die zu gross werden und nur nen subset draus gebraucht wird, (callback fall 1). Fuer alles andere brauchst sowas nich ...

Beschreib mal bisserl genauer was du genau brauchst ... glaub mit den begriffen bist da auch durcheinander gekommen.

Ciao ...

Dieser Post wurde am 02.05.2006 um 12:39 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
02.05.2006, 14:35 Uhr
~Starbuck
Gast


Gleich mal zu Beginn danke für die ausführlichen Erklärungen.

Wahrscheinlich reden wir hier bezüglich Begriffsbestimmungen ein bisschen nebebeinander her.

Ich versuch, nochmal die Situation genauer zu schildern:

Es gibt ein Programm (.exe), dass zusätzlich DLLs benutzt um Simulationen durchzuführen.
Um jetzt eigene (auf individuelle Hardware abgestimmte) Simulationen machen zu können,
gibt es einen Sourcecode (als Basis), aus dem man eine DLL erzeugt, die dann mit dem .exe und den anderen DLLs zusammenarbeiten kann.

In diesem Source Code gibt es eine Funktion, die von der externen DLL aufgerufen wird (_declspec dllexport). Bei der Initialisierung werden mit Hilfe von GetProcAddress() die Pointer von diversen Funktionen (die ich als Callback bezeichnet habe - sie befinden sich in einer der externen DLLs) geladen und in einem globalen struct gespeichert. Dabei gibt es Funktionen, die unsigned 32 bit Werte speichern können (in der externen DLL, aber ich weiß nicht wie sie dort gespeichert sind - was mir ja quasi egal sein kann).

Für meine Zwecke brauche ich Simulationsdaten, die in, teilweise in verschiedenen Sourcefiles befindlichen, mehreren Funktionen bekannt sein müssen. Derzeit löse ich das hauptsächlich über globale Variablen, die in anderen Files als extern deklariert sind.

z.B. also


C++:

extern DWORD dwMeineGlobaleVariable1;
extern DWORD dwMeineGlobaleVariable2;
...

void MeineFunktion(int Param1, int Param2)
{
   DWORD dwLokaleVariable;
  
   ...
dwMeineGlobaleVariable1 = 0;  // Schreiben
dwLokaleVariable = dwMeineGlobaleVariable2;   // Lesen

}





Der andere Weg ist:


C++:

extern struct MeinStruct;

void MeineFunktion(int Param1, int Param2)
{
   DWORD dwErgebnis, dwWert1;
  
   ...
  
   MeinStruct.SchreibeWert(Addresse, dwErgebnis);  // Schreiben
  
   MeinStruct.LeseWert(Addresse, &dwWert1);  // Lesen

  
}




So, ich hoffe, ich konnte es nun klarer ausdrücken.

LG

Starbuck

------------------
"I am NOT a fraking Cylon!"
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
02.05.2006, 15:27 Uhr
RHBaum



1.

Zitat:

In diesem Source Code gibt es eine Funktion, die von der externen DLL aufgerufen wird (_declspec dllexport).


wenn die externe Funktion pointer auf von dir implementierte funktionen haelt, um die bei bedarf aufzurufen, sinds hoechstwahrscheinlich doch callbacks ^^ Naja, theorethisch, die frage ist, ob deine (aus dem abgewandelten sourcecode) implementierte funktion direkt mit der externen Dll kommuniziert oder uebers hauptprogramm geht ^^
Denk mal geht nur uebers hauptprogramm, also deine dll brauch die anderen externen dlls nich anziehen oder ? (waere ne saubere loesung)
Aber das sind wirklich nur begriffe um die wir diskutieren ^^


erste Version die du schreibst ist die klassische c implementation ^^
zweite version ist ne an C++ angenaeherte version ...

Iss eigentlich ne Prinzipielle Stilfrage ... wenn du deine Dll mit plain C implementieren willst, also nur nen C-Compiler vorrraussetzt, (unabhaengig davon ob selber nen c++ compiler verwendest oder nich, die meisten uebersetzen dir auch C) dann ist version 1 soweiso klar.

Wenn du aber die vorteile von C++ verwenden willst, und soweiso auf klassen baust ... dann ne verbesserte version von variante 2.

Verbessert ?

1. member funktionen an strukts: ?
uebersetzt jeder [b]C++[b/] compiler, klar, aber nur aus faulheit struct statt class zu verwenden um sich den zugriffsmodifizierer zu sparen ???
structs nimmt man um plain C Datentypen zusammenzubauen ... falls die teil ner schnittstelle sind das nen C Compiler mit klarkommt, und um den Nutzer in C++ zu signalsieren, dass da nur reine Daten hinterstecken ... sobald ne logic und ne kapselung dahinnersteckt -> class (nen c-compiler kaem eh ned klar damit).

2.
extern struct MeinStruct;

warum extern ?

deine Klasse schoen in ner getrennten .h und .cpp bauen ...
irgendwo hasst du doch die cpp datei, die deine exportierten funktionen definiert ....
die kaann doch bei version 2 nimmer C kompatibel sein, da sie eh memberaufrufe enthaelt ...

also nen

meineDll.cpp // was weiss ich fuern namen ?


C++:

#include MeinClass.h // wir brauchen MeinClass

MeinClass gMeinClass; // ne globale instanz in deiner Impl ....

void MeineFunktion(int Param1, int Param2)
{
   DWORD dwErgebnis, dwWert1;
  
   ...
  
   gMeinClass.SchreibeWert(Addresse, dwErgebnis);  // Schreiben
  
   gMeinClass.LeseWert(Addresse, &dwWert1);  // Lesen

  
}

// hier auch noch alle deine anderen Impl's ....  der schnittstelle ...




Das extern braeuchtest nur, wenn Du Deine Implementationen aus der .h Datei ueber mehrere Cpp dateien verteilst ... nur wenn die in allen deinen verteilten cpp dateien brauchst, musst eine cpp datei festlegen wo deine globale variable definierst, oder du legst noch mal ne extra cpp datei fuer an ....

Ciao ..

Dieser Post wurde am 02.05.2006 um 15:31 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
02.05.2006, 16:12 Uhr
~Starbuck
Gast


Danke RHBaum für die nochmals sehr ausführliche Erklärung.

Bei dem struct hab ich mich vertan, das ist natürlich kein extern, sondern eine "normale Instanz" (und wird auch über h.file in mehreren .cpp Files bekannt gemacht).

Das große Problem bei der ganzen Geschichte ist, dass im Prinzip alles C Code (auch ohne Klassen) mit C++ Verpackung ist (auch mit MFC bei Dialogen usw.) und ich nicht wirklich gröber was ändern kann. Der Struct war auch vorgegeben, hier kann man aber sicher eine Klasse definieren.

Die Frage ist nur: kann bei Variante 1 wegen der globalen Variablen (ich hab ja nicht nur ein paar, sondern etwa 50 oder so) etwas schief gehen oder ist das an und für sich kein "technisches Problem" (Speicherbelegung, Compiler, Betriebssystem, ...), sondern nur ein "Stilproblem"?

LG

Starbuck

------------------
"I am NOT a fraking Cylon!"
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
02.05.2006, 16:22 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Technisch gesehen kann da nichts schief gehen solange du dir bewusst machst das ein Globale Variable nur für die jeweilige Instanz der Dll gültig ist.
D.h. wenn mehrere Programm die DLL aufrufen hat jedes Programm seine eigenen Versionen der globalen Variablen. Also so wie RHBaum das gesagt hat.

Wenn du das nicht willst dann musst du die Variablen in einem bestimmten Segment anlegen, aber ich denke das das unwichtig für dein Problem ist.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
03.05.2006, 11:01 Uhr
RHBaum




Zitat:

twas schief gehen oder ist das an und für sich kein "technisches Problem"


globale und normale variable ... hat fuer dich(programmierer) technisch eigentlich nur einen unterschied ...
bei der normalen variable hasst den lebenszyklus inklusive der Reihenfolgen voll in der hand. Bei der globalen hasst das nicht mehr ...
Das macht probleme beim beenden, wenn die destrukturen der globalen variablen von anderen globalen variablen abhaengig sind ... (macht man ja auch nich sowas)
Ansonsten isses eher unproblematisch ...

Es ist also eher nen "Stilproblem" ....

Warum sind globale variablen poese ??? (zumindest sagen das die programmierer)

Ganz einfach, weil die namen der variablen allgegenwertig im globalen Scope vegetieren. Und viellecht das der Lebenszyklus laenger ist als benoetigt (wie gesagt gibt faelle da ist das gewollt, deshalb kommt man manchmal nicht ohne globale variablen aus). Und C/C++ prinzipbedingt bei namenscollisionen nicht warnt. ....
Die Effekte koennen weitreichend sein ....

Wenn du der einzige bist, der sich damit rumschlaaegt, kein Thema ...dann hasst das unter kontrolle.
Aber globale variablen kann man sich sonstwo "einfangen" ... libs zum groessten teil ^^
Und wenn man als user die globalen variablen ned kennt (keine dokumentation, weil Implementierungsdetail, der eigentliche user der lib nicht direkt mit arbeiten soll ... etc) und du deklarierst ne variable mit selbigen namen -> die globale variable wird verdeckt -> Katastrophe. Im Besten Falle belohnt dich der compiler mit 1000enden fuer dich total unverstaendlichen fehlermeldungen. ^^

Und troeste dich, bei Dlls braucht man haeufiger globale variablen ... prinzipbedingt ... und zwar hasst du zwar ne main(DllMain) die iss aber nicht programmablaufbestimmend ... also musst da meist mit globalen sachen arbeiten ...

(wie gesagt unter c++ nimmt man lieber statische members) ...

Ciao ...

Dieser Post wurde am 03.05.2006 um 11:19 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
03.05.2006, 11:04 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Das verstehe ich jetzt allerdings nicht. Was hast du in deinem Program mit globalen Variablen in einer Dll zu schaffen?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
03.05.2006, 11:24 Uhr
RHBaum




Zitat:

Was hast du in deinem Program mit globalen Variablen in einer Dll zu schaffen?


Wenn das an mich gerichtet war: nix !
War nur allgemein warum man globale variablen prinzipiell vermeiden sollt ...

das variablen aus ner dll nicht mit variablen in der exe collidieren, iss was anderes ...
Die Collisionen treten auf wenn du libs oder .h(mit impl) einbindest ... nicht alles was man wiederverwenden will presst man gleich in ne Dll ^^

Ciao ...
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: