Verwalten des Arbeitsspeichers
Die API von Visual FoxPro bietet direkten Zugriff auf den dynamischen Speichermanager von Visual FoxPro. Für API-Routinen, die Speicherzuweisungen erfordern, wird ein Speicherbezeichner oder -Handle zurückgegeben. Die Segmentladearchitektur von Visual FoxPro verwendet Kennungen anstelle von Zeigern, damit der Speicher effizienter verwaltet werden kann.
Anmerkung Die in diesem Abschnitt beschriebenen Techniken zur Verwaltung von Arbeitsspeicher mit der Visual FoxPro-API gelten sowohl für ActiveX-Steuerelemente als auch für FLL-Bibliotheken.
Verwenden von Handles
Der Begriff Handle bezieht sich auf eine Speicherkennung, die im Wesentlichen ein Index für ein Array aus Zeigern ist. Die Zeiger zeigen auf Speicherblöcke, die Visual FoxPro kennt. In der API erfolgen fast alle Verweise auf Arbeitsspeicher über Kennungen, nicht über die herkömmlichen C-Zeiger.
So reservieren und verwenden Sie Arbeitsspeicher in Ihrer Bibliothek
Reservieren Sie mit _AllocHand( ) ein Handle.
Sperren Sie das Handle mit _HLock( ).
Wandeln Sie das Handle mit _HandToPtr( ) in einen Zeiger um.
Verweisen Sie mit dem Zeiger auf den Speicherbereich.
Heben Sie die Sperre des Handles mit _HUnLock( ) wieder auf.
Anmerkung Schreiben Sie nicht in eine Memodatei, bevor Sie _AllocMemo( ) aufrufen, um eine Beschädigung der Memodatei zu vermeiden.
Zur Adressierung des zugeteilten Speichers müssen Ihre API-Routinen durch Aufrufen der _HandToPtr( )-Routine das Handle in einen Zeiger umwandeln. Auch wenn der Speichermanager von Visual FoxPro den Speicher neu organisieren muss, um mehr zusammenhängenden Arbeitsspeicher für spätere Speicheranforderungen zu erhalten, bleibt das Handle dasselbe. Zusätzlich werden Routinen bereitgestellt, die zugeteilten Arbeitsspeicher vergrößern, verkleinern, freigeben bzw. sperren können.
Wenn Sie externe Routinen erstellen, sollten Sie versuchen, jeweils möglichst wenig Arbeitsspeicher zu verwenden. Wenn Sie eine externe Routine schreiben, die den Speicher dynamisch zuteilt, sollten Sie versuchen, mit möglichst wenig Speicher auszukommen. Besondere Vorsicht ist angebracht, wenn Sie große Speicherzuteilungen langfristig sperren. Denken Sie daran, Speicherkennungen mit _HUnLock( ) freizugeben, wenn sie nicht mehr gesperrt sein müssen, da die Leistungsfähigkeit von Visual FoxPro durch gesperrte Speicherhandles beeinträchtigt werden kann.
Vorsicht Wenn Sie sehr viel dynamischen Speicher verwenden, steht für Visual FoxPro entsprechend weniger Arbeitsspeicher für Puffer, Fenster, Menüs usw. zur Verfügung. Außerdem wird das Leistungsverhalten von Visual FoxPro beeinträchtigt, da der Arbeitsspeicher, der für Anforderungen von API-Routinen verwendet wird, vom Speichermanager von Visual FoxPro verwaltet wird. Die Zuteilung und Aufrechterhaltung umfangreicher Handles kann dazu führen, dass Visual FoxPro nicht mehr über ausreichend Arbeitsspeicher verfügt und abstürzt. In der Visual FoxPro-Umgebung gibt es keinen Arbeitsspeicherschutz. Die externe API-Routine kann nicht alle Gültigkeitsprüfungen durchführen, die in einem standardmäßigen Visual FoxPro-Programm enthalten sind. Wenn Sie den Arbeitsspeicher beschädigen, werden Meldungen wie "Fehler bei überschrittenem Handle", "Interner Konsistenzfehler" und "Bei der Komprimierung wurde überschrittener Knoten gefunden" ausgegeben.
Anhand der folgenden Funktion einer FLL-Bibliothek wird die Reservierung von Arbeitsspeicher verdeutlicht. Im Beispiel wird mit _RetDateStr( ) ein Wert des Visual FoxPro-Datentyps Datum zurückgegeben, wobei angenommen wird, dass der Parameter des Typs Zeichen ein korrektes Datum enthält:
#include <Pro_ext.h>
void dates(ParamBlk *parm)
{
MHANDLE mh;
char *instring;
if ((mh = _AllocHand(parm->p[0].val.ev_length + 1)) == 0) {
_Error(182); // "Insufficient memory"
}
_HLock(parm->p[0].val.ev_handle);
instring = _HandToPtr(parm->p[0].val.ev_handle);
instring[parm->p[0].val.ev_length] = '\0';
_RetDateStr(instring);
_HUnLock(parm->p[0].val.ev_handle);
}
FoxInfo myFoxInfo[] = {
{"DATES", (FPFI) dates, 1, "C"}
};
FoxTable _FoxTable = {
(FoxTable *) 0, sizeof(myFoxInfo)/sizeof(FoxInfo), myFoxInfo
};
Stapelspeicher (Stacks)
Das Steuerelement oder die Bibliothek, das bzw. die Sie erstellen, hat keinen eigenen Stapelspeicher. Stattdessen nutzt das Steuerelement oder die Bibliothek den Stapelspeicher des aufrufenden Programms, in diesem Fall also den Visual FoxPro-Stapelspeicher. Sie können die Größe des Stapelspeichers von Visual FoxPro weder steuern noch die Größe des für ein ActiveX-Steuerelement oder eine FLL-Datei verfügbaren Stapelspeicherplatzes beeinflussen.
Unter Normalbedingungen ist diese Unterscheidung nicht von Bedeutung. Der Stapelspeicher von Visual FoxPro ist in der Regel groß genug, um die automatischen Variablen zu fassen, die Sie in einem Steuerelement oder einer Bibliothek möglicherweise reservieren müssen. Wenn der Stapelspeicherplatz knapp wird, können Sie immer noch dynamisch zusätzlichen Speicher aus dem Heap zuteilen.
Befolgen von Handleregeln
Die folgenden Regeln gelten für den Besitz von Handles und die Verantwortung für deren Freigabe:
Die Anwender müssen alle Handles freigeben, die sie zuteilen, und zwar einschließlich der Handles, die von Funktionen wie _Load() zugeteilt werden.
_Load() erstellt nur dann ein Handle, wenn die Speichervariable, die Sie gerade laden, eine Zeichenfolge ist (d. h.
ev_type = 'C'
). Alle anderen Datentypen speichern ihre Werte in der Struktur Value selbst, während das Laden einer Zeichenfolge ein Handle (MHANDLE) in das Feldev_handle
der Struktur Value legt.Bei einer FLL-Bibliothek übernimmt Visual FoxPro die Freigabe aller mit _RetVal( ) zurückgegebenen Handles. Benutzer dürfen diese Handles nicht freigeben, und zwar auch dann nicht, wenn sie sie zuteilen.
Benutzer dürfen Handles nicht freigeben, die ihnen in ihrem
ParamBlk
übergeben wurden.Vorsicht Wenn Sie eine externe Routine schreiben, die Funktionsaufrufe enthält, sollten Sie unbedingt alle obigen Regeln beachten und die Rückgabewerte prüfen. Ein fehlerhafter Zeiger oder Handleverweis könnte die internen Datenstrukturen von Visual FoxPro beschädigen und dadurch einen sofortigen Programmabbruch oder spätere Probleme verursachen, wodurch wiederum Datenverluste entstehen können.
Siehe auch
Zugriff auf Visual FoxPro-Variablen und -Felder | Erstellen und Debuggen von Bibliotheken und ActiveX-Steuerelementen | Zugreifen auf die Visual FoxPro-API | Erweitern von Visual FoxPro mit externen Bibliotheken | _AllocHand( ) | Erstellung der API-Bibliothek