home *** CD-ROM | disk | FTP | other *** search
- Neuigkeiten für Turbo Pascal 6.0:
- "FreePtr" umschifft, und "realloc" funktioniert doch! (Trickkiste 6'91)
-
- Die Unit "Realloc" die Sie ebenfalls auf dieser Diskette finden,
- implementiert für Turbo Pascal 5.x die
- Funktion »ChangeMem«, mit deren Hilfe sich die Größe des
- Speicherbereichs, den eine Zeigervariable auf dem Heap
- belegt, während der Programmlaufzeit verändern läßt. Eine
- sehr nützliche Sache, wenn man viel mit dynamischen Daten
- arbeitet.
-
- Wenn Sie jedoch versuchen, diese Unit auch unter der neuen
- Turbo-Pascal-Version 6.0 einzusetzen, erleben Sie eine
- Enttäuschung: Der Compiler weigert sich glattweg, den
- Quelltext zu verarbeiten.
-
- Was ist passiert? Daß mit Turbo-Pascal 6.0 etliche Neuerun-
- gen eingeführt wurden, ist nicht zu übersehen. Vor allem
- wären da die neue Entwicklungsumgebung, das Turbo-Vision-
- Paket sowie der integrierte Assembler zu nennen. Aber die
- einschneidendste interne Veränderung hat Borland am Heap-
- Manager der Laufzeitbibliothek vorgenommen -- und dies ist
- auch der Grund, warum alle Programme, die aktiv in die Heap-
- Verwaltung eingreifen, unter der Version 6.0 nicht mehr lau-
- fen. Gerd Cebulla hat sich die neuen Speizalitäten einmal
- angesehen.
-
- Die Prozeduren "New"/"Dispose", "GetMem"/"FreeMem" sowie
- "Mark"/"Release" gibt es nach wie vor. Auch die Systemvaria-
- blen "HeapOrg" und "HeapPtr" sind noch vorhanden: "HeapOrg"
- ist ein Zeiger auf den Beginn des Heap und bleibt während
- des gesamten Programmlaufs konstant, "HeapPtr" dagegen ent-
- hält die Startadresse des freien Heap. Neu hinzugekommen ist
- die Variable "HeapEnd", die auf das Ende des Heap und damit
- auch auf das Ende des Programmspeichers zeigt.
-
- Die Fragmentliste jedoch, in der die Turbo-Pascal-Versionen
- bis 5.5 die freien Bereiche des Heap festhielten, existiert
- nicht mehr! Oder präziser ausgedrückt: Die Laufzeitbiblio-
- thek von Turbo-Pascal 6.0 verwaltet die "Löcher" im Heap
- nicht mehr in Form einer Tabelle am oberen Ende des Spei-
- chers, sondern als einfach verkettete dynamische Liste. Je-
- desmal, wenn Sie mit "Dispose" oder "FreeMem" eine dynami-
- sche Variable freigeben, werden die ersten acht Byte des so
- entstandenen Lochs mit einem Record belegt, den man wie
- folgt definieren könnte:
-
- TYPE
- FreePtr = ^FreeRec;
- FreeRec = RECORD
- Next : FreePtr;
- Size : Pointer;
- END;
-
- Das Feld "Next" ist dabei ein Zeiger auf das nächste Loch;
- wenn sein Wert mit dem von "HeapPtr" identisch ist, handelt
- es sich um das letzte Glied der Liste. Das Feld "Size" ent-
- hält die Größe des Lochs, allerdings in etwas ungewöhnlicher
- Form: nämlich als eine Art normalisierter Zeiger. Das bedeu-
- tet, im höherwertigen Word von "Size" ist die Anzahl der
- Paragraphen (16-Byte-Einheiten) verzeichnet, und im nieder-
- wertigen Word stehen die restlichen Byte, die bei der Divi-
- sion durch 16 übrigbleiben.
-
- Die Adresse des allerersten Lochs im Heap entnehmen Sie der
- Systemvariablen "FreeList"; wenn "FreeList" gleich "HeapPtr"
- ist, enthält der Heap keine Löcher. Bleibt nur noch zu klä-
- ren, wozu die Zeigervariable "FreeZero" dient, die ebenfalls
- in der Unit "System" definiert ist und beim Programmstart
- auf den Wert »nil« initialisiert wird. Die Handbücher und
- die integrierte Hilfestellung schweigen sich dazu aus, und
- in Borlands Dokumentationsdatei "SYSTEM.INT" findet sich nur
- die nebulöse Anmerkung "must be zero".
-
- Des Rätsels Lösung ergibt sich erst nach einigem Nachdenken.
- Da "FreeZero" gleich hinter "FreeList" deklariert wird, sind
- die beiden Variablen auch im Datensegment an direkt aufein-
- anderfolgenden Adressen gespeichert. Somit läßt sich das
- Variablenpaar "FreeList"/"FreeZero" auch als Record vom Typ
- "FreeRec" behandeln, wobei der Platz des Feldes "Size" durch
- "FreeZero" eingenommen wird und sein Wert in diesem speziel-
- len Fall natürlich immer Null betragen muß! Dieses Verfahren
- fällt zwar eindeutig in die Kategorie "dirty tricks" - aber
- es funktioniert und spart nebenbei eine ganze Menge Verwal-
- tungsaufwand.
-
- Soviel zu den Grundlagen. Die Unit "ReAlloc2" wurde für die
- Turbo-Pascal-Version 6.0 zwar gründlich überarbeitet, der
- Aufruf der Funktion "ChangeMem" ist aber gleichgeblieben:
-
- PNew := ChangeMem(P, OldSize, NewSize);
-
- Der Parameter "P" enthält die Adresse der dynamischen Varia-
- ble, "OldSize" ihre derzeitige Größe und "NewSize" die ge-
- wünschte neue Größe. Das Funktionsergebnis ist ein Zeiger
- auf die neue Adresse der dynamischen Variable. Falls auf dem
- Heap nicht mehr genug Platz verfügbar ist, wird der Wert
- "NIL" zurückgegeben - vorausgesetzt daß Sie die Systemvaria-
- ble "HeapError" auf eine eigene Fehlerroutine gesetzt haben,
- die im einfachsten Fall wie folgt aussehen könnte:
-
- FUNCTION HeapFunc(Size : WORD) : INTEGER; FAR;
- BEGIN
- HeapFunc := 1;
- END;
-
- Um andere Anwendungen an die neueste Version von Turbo
- Pascal anzupassen, wäre natürlich eine Standard-Unit
- willkommen. Wir sind bereits am Planen, aber vielleicht
- fällt Ihnen ja schon jetzt etwas ein...
-