global
global
Deklaration eines globalen Datenbereichs
Details
- Siehe: Verwandte Befehle ,
local,VarAllocate (),VarInstance (),VarFree ()
Die Definition eines globalen Datenbereiches wird mit dem Schlüsselwort global eingeleitet. Jeder globale Datenbereich muss einen eindeutigen Namen besitzen, der nach dem Schlüsselwort angegeben wird. Der Name kann unabhängig von den im Datenbereich deklarierten Variablen definiert werden.
Pro Prozedur können bis zu 65.000 globale und lokale Datenbereiche verwendet werden. Da der Speicher eines globalen Datenbereichs erst zur Laufzeit mit dem Befehl VarAllocate () angelegt wird, sollten für unterschiedliche Bereiche einer Applikation gegebenenfalls mehrere globale Datenbereiche definiert werden. Die Anzahl von Variablen in einem Datenbereich ist nicht beschränkt, allerdings kann ein einzelner Datenbereich nicht mehr als 4 MB Speicher belegen.
Von einem globalen Datenbereich können mehrere 'Instanzen' angelegt werden, indem VarAllocate () mehrfach aufgerufen wird. Der Wechsel zwischen den Speicherbereichen erfolgt dann mit VarInstance ().
Der globale Datenbereich muss in allen Prozeduren definiert sein, in denen er benutzt werden soll. Die Definition des Datenbereiches muss somit in einer Prozedur erfolgen, die in alle Prozeduren mit der Compileranweisung @I eingebunden wird. Der Datenbereich behält solange seine Gültigkeit, bis er mit dem Befehl VarFree () gelöscht wird.
Eine Variable wird deklariert durch <Variablenname> : <Variablentyp>;. Nach dem Typ der Variablen muss ein Semikolon stehen. Es können auch mehrere Variable gleichzeitig mit demselben Typ deklariert werden, indem einfach mehrere Variablennamen durch Komma getrennt angegeben werden.
Beispiel:
gString : alpha;
gWert : float;
gDate : date;
gTime : time;
Folgende Typen können verwendet werden:
Die Typen byte und word sind im wesentlichen nur bei Arrays von Bedeutung, da mit diesen Typen im Gegensatz zu int Speicherplatz gespart werden kann, sofern die zu erwartenden Werte im jeweiligen Wertebereich von byte bzw. word liegen.
Arrays
Eine Variable kann als Array deklariert werden. In diesem Fall folgt nach dem Typ die Anzahl der Elemente in eckigen Klammern. Sofern sich die Anzahl der benötigten Elemente erst zur Laufzeit ergibt, kann ein Array auch als dynamisch deklariert werden, indem keine Anzahl angegeben wird.
Beispiel:
global Common
{
gWerte : int[1000]; // 1000 Elemente von int
gNamensTab : alpha(100)[50]; // 50 Elemente von alpha(100)
gSortTab : byte[]; // dynamisches Array
}
Ein einzelnes Array kann nicht größer als 4 MB deklariert werden. Ein dynamisches Array muss zur Laufzeit per Prozedurbefehl mit der gewünschten Anzahl von Elementen im Speicher angelegt werden (VarAllocate ()). Die einzelnen Elemente eines Array werden später durch <namen>[<index>] angesprochen (zum Beispiel bSortTab[ 22 ]). Dabei hat das erste Element immer die Nummer 1, die Nummer des letzten Elements entspricht der Anzahl von Elementen im Array.
Benutzung konstanter Ausdrücke
Bei der Alphalänge und den Arrayelementen kann anstatt einem einzelnen Wert ein konstanter Ausdruck benutzt werden. Konstante Ausdrücke müssen vom Typ int sein und dürfen keine Felder, Variablen oder Funktionen enthalten. Symbolische Konstanten und konstante Werte sind zulässig.
Beispiel:
gSortTab : byte[iSortSize * 4 + 100];
Dabei ist iSortSize eine symbolische Konstante. Zulässig sind alle ganzzahligen Operationen und die Verwendung von Klammerebenen.
Gültigkeitsbereich
Der Gültigkeitsbereich eines globalen Datenbereichs lässt sich am sinnvollsten mit einem kleinen Beispiel verdeutlichen:
- Prozedur A: Prozedur B
- FWGMDXBLOCK0004: FWGMDXBLOCK0005
Hierbei wird in den beiden Prozeduren A und B der globale Datenbereich x deklariert. Intern wird aber ein globaler Datenbereich durch <Prozedurname>:<Datenname> angesprochen. Dadurch liegt die Variable 'gTest' in der Prozedur A im Datenbereich 'A:x', in der Prozedur B dagegen im Datenbereich 'B:x'. Somit ist die Variable 'gTest' in A und B nicht dieselbe. Um in beiden Prozeduren mit 'gTest' auch tatsächlich dieselbe Variable zu benutzen, ist folgende Konstruktion notwendig:
- Prozedur A: Prozedur B Prozedur C
- FWGMDXBLOCK0006: FWGMDXBLOCK0007 FWGMDXBLOCK0008
Jetzt wird der Datenbereich x in der Prozedur B deklariert, wodurch die Variable 'gTest' im Datenbereich 'B:x' liegt. Durch das Einbinden von B in den Prozeduren A und C greifen beide Prozduren jetzt auf dieselbe Variable 'gTest' zu.
Dieses Verfahren garantiert, dass von gemeinsam benutzten globalen Datenbereich nur eine einzige Deklaration existiert, wodurch nicht identische Mehrfachdeklarationen vermieden werden. Globale Datenbereiche müssen daher immer dann in gesonderten Prozeduren deklariert werden, wenn mehrere Prozeduren denselben Datenbereich verwenden wollen. Dies ist der Regelfall, jedoch macht es auch durchaus Sinn, einen Datenbereich direkt in einer Prozedur zu deklarieren, anstatt die Deklaration einzubinden. Dadurch wird der Datenbereich praktisch 'privat', dass heißt keine andere Prozedur hat Zugriff auf diesen Datenbereich.
Damit sichergestellt ist, dass bei Änderungen einer Deklaration keine ungültigen Prozeduren entstehen (zum Beispiel wenn Variablen aus dem Datenbereich entfernt wurden), existieren zwei zusätzliche Mechanismen:
- Laufzeitkontrolle Beim Starten einer Prozedur wird automatisch überprüft, ob die von der Prozedur benutzten Datenbereiche bereits im Speicher vorhanden sind. Ist dies der Fall, wird überprüft, ob der vorhandene Datenbereich in Bezug auf Größe und Anzahl der Variablen mit der in der Prozedur benutzten Deklaration übereinstimmt. Ist dies nicht der Fall, so entsteht ein Laufzeitfehler. Mit dieser Überprüfung können die meisten Inkompatibilitäten zur Laufzeit entdeckt werden.
- Übersetzen abhängiger Prozeduren Zur völligen Sicherheit können nach Änderung einer Prozedur alle diejenigen Prozeduren übersetzt werden, die die geänderte Prozedur einbinden. Eine entsprechende Funktion ist bei der Übersetzung von Prozeduren vorhanden.
Lebensdauer
Die Lebensdauer eines globalen Datenbereichs beginnt mit der Speicheranforderung per Prozedurbefehl (VarAllocate ()). Bei Datenbereichen, die ständig verfügbar sein müssen empfiehlt es sich, diese im Ereignis EvtInit des Frames anzulegen oder in der Eigenschaft DbVar eines Applikations- oder MDI-Fensters anzugeben. Die Lebensdauer des Bereiches endet beim Löschen des Datenbereiches mit VarFree () (zum Beispiel im Ereignis EvtTerm) oder beim Entladen des Applikations- oder MDI-Frames. Spätestens beim Entladen der Datenstruktur werden ebenfalls die globalen Datenbereiche freigegeben.