Der HEAP DEBUGGER V2.0 fr BORLAND PASCAL V7.0 (DOS, DOS/DPMI, WINDOWS) Copyright 1995 by AIT GmbH Alte Gasse 12 - 86152 Augsburg Germany Tel. +49 (821) 514868 Fax: +49 (821) 514831 FIDO-Net: Karsten Strobel @ 2:2480/300.7 Internet: kstrobel@gewi.muc.nacamar.de INHALT EINFšHRUNG Der Sinn des Heap Debuggers ......................................... 3 Was der Heap Debugger kann .......................................... 3 Was der Heap Debugger NICHT kann .................................... 3 Der Umgang mit dynamischem Speicher ................................. 3 Versionen und Zielplattformen ....................................... 4 Liste der Dateien ................................................... 5 Sharewarekonzept .................................................... 5 Lizenzbedingungen ................................................... 5 Nutzungsempfehlungen und Haftungsausschlsse ........................ 6 ANWENDUNG DES HEAP DEBUGGERS Den Heap Debugger einbinden ......................................... 6 Compiler- und Linkereinstellungen ................................... 7 Wenn die Initialisierung fehlschl„gt ................................ 7 Der Heap Debugger Report ............................................ 8 Besondere Meldungen im Heap Debugger Report ......................... 9 Interpretation des Reports .......................................... 10 Auffinden von Bugs .................................................. 11 Arbeiten mit einem externen Debugger ................................ 11 Compilerschalter in USEHDEB ......................................... 12 HEAP DEBUGGING IM DETAIL Overlays ............................................................ 13 DLLs ................................................................ 13 Programminstanzen (Windows) ......................................... 14 Interrupts .......................................................... 14 Stabilit„t und Performance .......................................... 14 Eingriffsm”glichkeiten fr den Programmierer ........................ 15 BEKANNTE EINSCHRŽNKUNGEN UND PROBLEME Mark/Release ........................................................ 16 MemAllocSeg ......................................................... 17 BGI ................................................................. 18 TMemoryStream ....................................................... 18 Heapberlauf ........................................................ 18 Programmabbruch ..................................................... 19 WINCRT .............................................................. 19 Seite 3 EINFšHRUNG _____________________________________________________________ ___ Der Sinn des Heap Debuggers ________________________________________ Der Heap Debugger berwacht (fast) alle vom Programm vorgenommenen Heap- Operationen und fhrt unter anderem eine Liste ber alle nicht freigege- benen Heapspeicherbereiche. Der Programmierer, der den Heap Debugger w„hrend der Entwicklungsphase in sein Programm einbindet, wird nach je- dem Programmabschluá auf briggebliebene Speicherbl”cke hingewiesen. Der Heap Debugger macht das Auffinden der Fehlerquellen extrem einfach, weil er (meistens) einen Hinweis auf die Sourcecodestelle (Dateiname und Zeile) liefert, an der die inkorrekte Heap-Operation vorgenommen wurde bzw. an der ein sp„ter nicht wieder freigegebener Speicherblock allo- ziert wurde. Hierzu bedient sich der Heap Debugger der Debug-Informationen fr den externen Debugger, die (optional) an das vom Compiler erzeugte EXE-File angeh„ngt werden. ___ Was der Heap Debugger kann _________________________________________ Der Heap Debugger berwacht alle Allokationen von Heapspeicher, die mit den Befehlen - GetMem - New - FreeMem - Dispose vorgenommen werden. Auch Aufrufe dieser Routinen aus der Run-Time- Library und aus Programmteilen heraus, die nicht im Sourcecode vorliegen (z.B. fremde TPUs), werden bercksichtigt. Alle nicht korrekt deallokierten Heapspeicherbl”cke und sonstige fehler- hafte Heap-Operationen werden im Heap Debugger Report ausgegeben. ___ Was der Heap Debugger NICHT kann ___________________________________ Folgende Heap-Operationen k”nnen vom Heap Debugger NICHT mitverfolgt werden: - Mark und Release (drfen gar nicht verwendet werden !) - direkte Operationen mit dem globalen Heap (DPMI+Windows), also alle "Global..."-Aufrufe - direkte Operationen mit dem lokalen Heap (Windows), also alle "Local..."-Aufrufe ___ Der Umgang mit dynamischem Speicher ________________________________ In Programme, die intensiv mit Heapspeicher umgehen, schleichen sich nicht selten heimtckische Programmierfehler ein: Wenn n„mlich dynamisch angeforderte Speicherbereiche nicht korrekt wieder freigegeben werden, schrumpft der noch verfgbare Heapspeicher nach und nach so weit zu- Seite 4 sammen, daá irgendwann fr eine neue Anforderung nicht mehr gengend Platz zur Verfgung steht und das Programm abbricht oder -strzt. Zum v”lligen Aufzehren des Heapspeichers kommt es natrlich nur, wenn Allokationen ohne entsprechende Deallokationen nicht nur einmal, sondern wiederholt durchgefhrt werden. Wenn dieses z.B. mit der Anwahl einer bestimmten Programmfunktion durch den Benutzer verbunden ist, dann kann dies vielleicht einige hundert Male gut gehen, bis der brige Heapspei- cher aufgebraucht ist. So intensiv werden aber Programme nur selten vom Programmierer getestet. Also kommen so bedingte Abstrze in der Regel erst beim Benutzer vor, der dafr natrlich keine Erkl„rung hat. Es gibt auch Allokationen, die nur einmalig, also zum Beispiel in der Initialisierungsphase vorgenommen werden, weil das Programm Speicher- platz fr quasi-statische Variablen ben”tigt. Solche Variablen (bzw. Strukturen oder Objekte) k”nnte der Pogrammierer auch im Datensegment (als globale Variablen) allokierten, aber da die Gr”áe des Datensegmen- tes auf insgesamt 64KB beschr„nkt ist, wird manchmal der Heap als Aus- weg gew„hlt. Wenn solche (nur einmalig allokierten) quasi-statischen Variablen nicht wieder freigegeben werden, so ist dies nur ein Sch”n- heitsfehler, hat aber sonst keine Konsequenzen. Der Heap Debugger be- m„ngelt aber natrlich auch solche Delikte. Besonders tckisch sind Deallokationsfehler, d.h. fehlerhafte Freigaben von Heapspeicher. Ein Deallokationsfehler liegt vor, wenn bei der Freigabe von Heapspeicher eine falsche Adresse oder eine falsche L„nge angegeben wird, also zu der unternommenen Deallokation zuvor keine pas- sende Allokation erfolgt ist. Da sich die Runtime-Library weitgehend auf die Angaben des Programmierers verl„át, k”nnen Deallokationsfehler ver- heerende Folgen haben. Besonders die Objektorientierte Programmierung macht intensiv von Heap- speicher Gebrauch. Zu jeder neuen Instanz eines Objektes wird ein Heap- speicherblock fr die Felder des Objektes angefordert, der beim L”schen der Instanz wieder freigegeben werden muá. Hierzu bedient man sich der Befehle New und Dispose in der speziell fr OOP-Zwecke erweiterten Syntax. Auch "vergessene" Objekte konsumieren Heapspeicher. ___ Versionen und Zielplattformen ______________________________________ Der Heap Debugger wurde entwickelt und getestet mit Borland Pascal V7.0 und V7.01 mit den Zielsystemen - Real Mode (hierfr HDEB7?.TPU) - Protected Mode (hierfr HDEB7?.TPP) - Windows (hierfr HDEB7?.TPW) unter - DOS 6.2x - Windows V3.1 - Windows for Workgroups V3.11 - Windows NT 3.5 Workstation - OS/2 V2.11 Eine Version fr Delphi V1.0 fr Windows ist in Vorbereitung. Seite 5 ___ Liste der Dateien __________________________________________________ USEHDEB.PAS .... Unit zum Einbinden in Pascalprogramme, fr DOS, DOS/DPMI und WINDOWS HDEB7S.TPU ..... Der Kern des Heap Debuggers, nur bei Sharewareversionen, fr DOS/Real Mode HDEB7S.TPP ..... Der Kern des Heap Debuggers, nur bei Sharewareversionen, fr DOS/Protected Mode HDEB7S.TPW ..... Der Kern des Heap Debuggers, nur bei Sharewareversionen, fr Windows HDEB7F.TPU ..... Der Kern des Heap Debuggers, nur bei Vollversionen fr DOS/Real Mode HDEB7F.TPP ..... Der Kern des Heap Debuggers, nur bei Vollversionen fr DOS/Protected Mode HDEB7F.TPW ..... Der Kern des Heap Debuggers, nur bei Vollversionen fr Windows VIEWME.EXE ..... Der Heap Debugger in Bildern (VGA) README.TXT ..... Dieser Text (englisch) LIESMICH.TXT ... Dieser Text (deutsch) DIZFILES.ZIP ... Fr Sysops, nur in Sharewareversionen SHARWARE.ZIP ... Diese Datei ist nur in Vollversionen enthalten und enth„lt die Sharewareversion BESTELL.TXT .... Bestellformular (deutsch) ORDER.TXT ...... Bestellformular (englisch) ___ Sharewarekonzept ___________________________________________________ Der Heap Debugger ist Shareware, also KEINE Public Domain oder Freeware! Die ber Sharewarevertriebswege verbeitete Version des Heap Debuggers in den Dateien HDEB7S.* ("S"=Shareware) und die Begleitdateien und die Datei USEHDEB.PAS drfen zu Testzwecken genutzt und an andere weiterge- geben werden. Die Sharewareversion ist gegenber der Vollversion im Leistungsumfang beschr„nkt: Die Sharewareversion des Heap Debuggers verfolgt nur die ersten 50 Allokationen von Heapspeicherbl”cken. Alle folgenden Allo- kationen werden ignoriert. Bei šberschreitung des Sharewarelimits wird bei Ausgabe des Reports (bei Programmende) eine entsprechende Meldung ausgegeben. Registrierte Vollversionen des Heap Debuggers beinhalten die Dateien HDEB7F.* ("F"=Full). Diese Dateien drfen NICHT an Dritte weitergegeben oder ihnen zug„nglich gemacht werden. ___ Lizenzbedingungen __________________________________________________ Wer den Heap Debugger in der unbeschr„nkten Vollversion nutzen m”chte, muá eine Registrierung bei den Autoren vornehmen und erh„lt im Zuge der Lieferung der Vollversion eine Lizenz zur Nutzung der Vollversion auf einem einzelnen Arbeitsplatz. Bei Nutzung des Heap Debuggers auf mehreren Arbeitspl„tzen mssen auch mehrere Registrierungen bestellt werden. Hierfr bieten wir Staffel- preise an. Seite 6 Ein Registrierungsformular ist in der Datei BESTELL.TXT vorbereitet. Es ist ausdrcklich untersagt, die Vollversion des Heap Debuggers weiterzugeben. Dies betrifft insbesondere die Dateien HDEB7F.* ___ Nutzungsempfehlungen und Haftungsausschlsse _______________________ Obwohl wir den Heap Debugger vor der Ver”ffentlichung ausfhrlich getes- tet haben, k”nnen wir keine Garantie fr einwandfreie Funktion oder Feh- lerfreiheit dieser Software bernehmen. Wir empfehlen die Nutzung des Heap Debuggers w„hrend der Entwicklungs- phase. Nach Fertigstellung eines Softwareprodukts sollte unserer Meinung nach der Heap Debugger nicht mehr eingebunden werden. Der Heap Debugger soll Ihnen bei der Softwareentwicklung helfen, Fehler bei der Speicherverwaltung zu vermeiden oder zu beseitigen. Wir weisen aber auch auf die zus„tzlichen Gefahren fr die Stabilit„t einer Soft- ware, die den Heap Debugger einbindet, hin. N„heres hierzu siehe Ab- schnitt "Stabilit„t und Performance". Bei Lieferungen dieser Software erstreckt sich unsere Garantie aus- schlieálich auf die Lesbarkeit des gelieferten Datentr„gers. Wir ber- nehmen keinerlei Haftung fr Sch„den, die durch Benutzung des Heap Debuggers eventuell entstehen werden. ANWENDUNG DES HEAP DEBUGGERS ___________________________________________ ___ Den Heap Debugger einbinden ________________________________________ Um den Heap Debugger in ein eigenes Programm einzubinden, mssen Sie nur die Unit UseHDeb in die Uses-Klausel Ihres Hauptprogramms aufnehmen. Beispiel: PROGRAM MyProg; UseHDeb, \ / \/ USES Drivers, Objects, Views, Menus, ... Es ist sinnvoll, die Unit UseHDeb als erste Unit in der Uses-Klausel aufzufhren. Die Initialisierung des Heap Debuggers erfolgt ber den Initialisierungsteil dieser Unit. Erst nach der Initialisierung kann der Heap Debugger Heap-Operationen "beobachten". Deshalb sollte die Initia- lisierung von UseHDeb m”glichst vor der Initialisierung anderer Units, die eventuell schon Heap-Operationen machen, vorgenommen werden. Keine der Units, von denen die Units UseHDeb und HDeb7? ihrerseits di- rekt oder indirekt Gebrauch machen, nimmt in der Initialisierungsphase Heap-Allokationen vor. Der Heap Debugger erh„lt also von allen Heap- Operationen Kenntnis, sofern keine der vom Heap Debugger genutzten Units modifiziert worden sind. Seite 7 ___ Compiler- und Linkereinstellungen __________________________________ "D+": Der Heap Debugger wird nur initialisiert, wenn die Unit UseHDeb mit der Compileroption "D+" (Debug-Informationen ein) bersetzt wird. Das liegt daran, daá fast die gesamte Unit UseHDeb mit Hilfe der Klausel {$IFOPT D+}...{$ENDIF} von der Compilierung ausgeschlossen ist, wenn die Option D+ nicht eingeschaltet ist. Dieser Schalter kann also zum Ein- und Ausschalten des Heap Debuggers verwendet werden. Theoretisch k”nnte der Heap Debugger allerdings auch ohne eingeschaltetes D+ laufen. Fr alle anderen Units, die in Ihr Programm eingebunden werden, sowie fr das Hauptprogramm gilt: Nur wenn mit der Option D+ bersetzt wird, kann der Heap Debugger in seinem Report Referenzen auf diese Quellda- teien und Zeilennummern angeben. "Link-Puffer: Festplatte" und "Externer Debugger": Damit der Heap Debugger im Report Referenzen auf Quelldateien und Zei- lennummern liefern kann, mssen die dazu notwendigen Debug-Informa- tionen in das vom Compiler erzeugte EXE-File (bzw. DLL) geschrieben wer- den. Neben der Compileroption D+ werden dazu auáerdem die Einstellungen "Link-Puffer: Festplatte" und "Externer Debugger" ben”tigt. Unter Win- dows heiát die letzte Option "Debug-Info in EXE". "Unit-Verzeichnis: \BP\RTL\WIN" (DOS/DPMI und Windows): Die Unit UseHDeb ben”tigt im Protected Mode (DOS+Windows) die Unit WINPROCS. Diese befindet sich gew”hnlich im Verzeichnis "\BP\RTL\WIN". Da unter DOS dieses Verzeichnis normalerweise nicht als Unit-Verzeichnis (siehe Option-->Verzeichnisse) eingestellt ist, mssen Sie dieses Ver- zeichnis selbst in der Liste der Unit-Verzeichnisse erg„nzen. ___ Wenn die Initialisierung fehlschl„gt _______________________________ Die Initialisierung des Heap Debuggers wird von dem Initialisierungteil der Unit UseHDeb vorgenommen. Bei Fehlschlagen der Initialisierung gibt UseHDeb die Meldung "Heap Debugger konnte nicht initialisiert werden !" aus und stoppt das Programm mit dem Kommando HALT. Das Fehlschlagen der Initialisierung kann folgende Ursachen haben: - Sie verwenden eine modifizierte Run-Time-Library, die in einem fr den Heap Debugger wichtigen Punkt nicht mit dem Original von Borland bereinstimmt. - Sie verwenden ein von uns nicht getestetes Betriebssystem oder spezielle, von uns nicht getestete Tools (z.B. zur Speicherverwaltung). - Sie verwenden eine von uns nicht getestete Compilerversion. - Es wurden keine freien Interruptvektoren gefunden. Der Heap Debugger ben”tigt drei freie Interrupts. In diesem Falle ist wahrscheinlich unsere Testmethode zum Finden freier Interrupts verantwortlich. Es kommt selten vor, daá tats„chlich alle Interrupts belegt sind. - Der Heap Debugger ist schon initilisiert. Dies sollte bei Verwendung der Unit UseHDeb nicht vorkommen. Seite 8 Wenn bei Ihrem System die Initialisierung des Heap Debuggers fehlschla- gen sollte, dann versuchen Sie bitte zun„chst, Ihr Programm in einer von uns getesteten Konfiguration (z.B. MSDOS 6.2, ggf. Windows 3.1) ohne vorheriges Laden irgendwelcher spezieller Speichermanager oder Multi- tasker zu laden. Beobachten Sie, ob der Heap Debugger in dieser Konfi- guration initialisiert werden kann. Bitte informieren Sie uns ber Konfigurationen, in denen der Heap Debugger nicht betrieben werden kann (m”glichst per email). ___ Der Heap Debugger Report ___________________________________________ Der Heap Debugger gibt beim Beenden des untersuchten Programms einen Re- port aus. Dies geschieht in der Exit-Prozedur der Unit UseHDeb. Der Heap Debugger Report hat in der Regel folgenden Aufbau (Beispiel): HEAP DEBUGGER DIAGNOSE: 2 Pointer wurden registiert (*1) 1 Debug-Eintraege vorhanden (*2) auflisten (J/N) ? j (*3) (*4) (*5) (*6) (*7) |------(*8)------| Nr Pointer Size Flags Aufrufer Datei Zeile 2 1A41:0000 256 0000[122D]:0044 HEAPBUG.PAS 16 (*1): Hier wird angegeben, wieviele Heap-Allokationen der Heap Debugger insgesamt mitverfolgt hat. Diese Zahl enth„lt also noch keine Aussage ber eventuelle Fehler. (*2): Hier wird angegeben, wieviele Diagnosezeilen der Heap Debugger auszugeben hat. Im Idealfall sollte hier immer "0" stehen. Nicht alle, aber die meisten Diagnosezeilen deuten auf einen Program- mierfehler hin. (*3): Hier wird eine laufende Nummer aller vom Programm vorgenommener Allokationen ausgegeben. Bei Deallokationen (Flag "F") steht hier nichts. (*4): Hier wird die Adresse des allokierten bzw. deallokierten Heapspeicherblocks ausgegeben. Diese Adresse kann von Programmlauf zu Programmlauf variieren. (*5): Hier wird die Gr”áe des allokierten bzw. deallokieren Blocks ausgegeben. (*6): Die hier ausgegebenen Flags haben folgende Bedeutung (Kombinationen sind m”glich): keins: Es handelt sich um eine Allokation, zu der keine passende Deallokation erfolgt ist. "O" : Es handelt sich um die Daten einer Objektinstanz. Das ist der Datenbereich, der vom Constructor eines Objektes fr die Felder des Objektes (und anderes) bei jeder neuen Instanz angelegt wird. Als Aufrufer wird die Zeile mit dem Word "BEGIN" des Construktors angegeben, bzw. die Zeile mit dem Word "END" des Destructors bei Deallokationen. "F" : Bei dieser Diagnosezeile geht es um eine Deallokation (F=free). Was bei dieser Deallokation schiefgegangen ist, wird mit einem der folgenden Flags angegeben. Seite 9 "S" : Ein Heapspeicherblock wurde nicht mit der gleichen Block- l„nge (S=size) deallokiert, mit der er allokiert wurde. In diesem Falle wird dieses Flag sowohl in der Diagnosezeile der Allokation als auch in der der Deallokation ausgegeben. "M" : Zu einer Deallokation wurde keine passende Allokation gefunden (M=mismatch). Das heiát, daá versucht wurde, einen Heapspeicherblock zu deallokieren, dessen Adresse nicht bei einer vorangegangenen Allokation registriert worden ist. Dieses Flag tritt nur zusammen mit dem Flag "F" auf. (*7): Hier wird die Adresse der aufrufenden Programmstelle ausgegeben. An dieser Programmstelle wurde die in der Diagnosezeile angegebene Heap-Operation aufgerufen. Die Segmentadresse dieser Stelle ist sowohl als virtuelle Segmentadresse (in eckigen Klammern "[]") als auch aktuelle Segmentadresse angegeben. Die virtuelle Segment- adresse wird vom Linker vergeben und ist die Adresse relativ zur Adresse 0000. Die aktuelle Adresse wird beim Laden des Programms vergeben und ist abh„ngig von der Stelle, an die das Programm in den Speicher geladen wird. Die virtuelle Adresse findet sich im MAP-File des Programms wieder. Die aktuelle Adresse kann von Pro- grammlauf zu Programmlauf variieren. (*8): Hier wird die Sourcecodestelle (Dateiname und Zeilennummer) ange- geben, die sich die Aufrufer-Adresse bezieht. Voraussetzung dafr ist, daá berhaupt Debug-Informationen im EXE-File existieren. Sind keine Debug-Informationen vorhanden, dann wird hier "keine Info." angezeigt. Wenn zwar Debug-Informationen vorhanden sind, aber die Sourcecodestelle zu der Aufrufer-Adresse trotzdem nicht gefunden werden konnte, dann wird hier "?" angezeigt. ___ Besondere Meldungen im Heap Debugger Report ________________________ Folgende Meldungen k”nnen im Heap Debugger Report in Ausnahmef„llen auf- treten: "Programm durch HALT(nnn) gestoppt" Diese Meldung erscheint, wenn das Programm gezielt mit dem Befehl HALT(nnn) gestoppt wurde. Der Exitcode wird mit nnn angegeben. "Laufzeitfehler nnn bei ssss:oooo, Datei: ________ Zeile: _____" Wenn das Programm durch einen Laufzeitfehler abgebrochen wird, erscheint diese Meldung. Als zus„tzliche, ntzliche Information wird die Programmstelle des Laufzeitfehlers (Quelldateiname und Zeilennummer) ausgegeben, sofern diese Information verfgbar ist. "interner Fehler 203 im Heap Debugger aufgetreten" Diese Meldung bedeutet, daá dem Heap Debugger zur Laufzeit nicht gen- gend Heapspeicher zur Verfgung stand, um alle Heap-Operationen auf- zeichnen zu k”nnen. "Shareware-Limit ueberschritten! Es wurden nur 50 pointer verarbeitet!" Diese Meldung wird nur von der Sharewareversion ausgegeben und besagt, daá das Sharewarelimit von 50 berwachten Allokationen zur Laufzeit berschritten worden ist. Seite 10 ___ Interpretation des Reports _________________________________________ Natrlich sollte man immer anstreben, am Ende eines Programmlaufs vom Heap Debugger die Meldung "0 Debug-Eintraege vorhanden" gemacht zu bekommen. Wenn der Heap Debugger w„hrend der gesamten Entwicklungszeit einer Applikation kontinuierlich eingesetzt wird, dann l„át sich eine nach einem Testlauf pl”tzlich auftauchende andere Meldung meist sehr leicht mit der zuletzt vorgenommenen Programm„nderung in Zusammenhang bringen. Wenn die Sache einmal nicht so einfach ist, muá man die Diagnose des Heap Debuggers zun„chst einmal interpretieren, um dem Problem auf die Schliche zu kommen. Hierzu sollte man sich die folgenden Fragen stellen: - Ist die Anzahl der Diagnoseeintr„ge immer gleich oder variiert diese Anzahl ? Soweit die Anzahl nicht variiert, handelt es sich offenbar um einmalig vorkommende Fehler im Programm. Es gibt F„lle, bei denen die Bezeichnung Fehler sogar etwas zu scharf gew„hlt ist. Manche Programme legen n„mlich quasi-statische Variablen auf dem Heap an, und geben diese dann am Ende nicht wieder frei. So ein Verhalten ist zwar nicht sonderlich sch”n und sollte deshalb vermieden werden; es hat andererseits aber auch keine schlimmen Konsequenzen. - L„át sich das Anwachsen der Anzahl der Diagnosezeilen mit einer bestimmten Funktion meines Programms in Zusammenhang bringen ? Wenn die Anzahl w„chst, dann sollte man versuchen, den sich offenbar wiederholenden Fehler auszumachen. Meistens ist das sehr einfach, wenn n„mlich der Heap Debugger fr mehrere Eintr„ge die selbe Aufruferadresse ausgibt. Es handelt sich dann wohl um einen Fehler, der immer dann zum Tragen kommt, wenn eine bestimmte Programmfunktion ausgel”st wird. Solche Fehler sollte man auf jeden Fall beseitigen, da sie den gefrchteten "Ged„chtnisschwund" ausl”sen. - Wurde in einzelnen Diagnosezeilen irgendein Flag eingetragen ? Soweit nicht, handelt es sich bei den Diagnosen des Heap Debuggers um Hinweise auf "klassische" Fehler, n„mlich auf das unterlassene Freigeben "normaler" Heapspeicherbl”cke, die mittels GetMem oder New angefordert wurden. Die Sourcecodereferenz verweist auf die Stelle, an der diese Anforderung geschehen ist. - Wurde in einzelnen Diagnosezeilen das Flag "O" eingetragen ? Soweit ja, weist der Heap Debugger auf Verfehlungen im Zusammenhang mit Objekten hin. Wird z.B. nur ein "O" eingetragen, dann handelt es sich um nicht freigegebene Instanzdaten eines Objektes, welche (im allgemeinen) mittels New in der OOP-Variante, n„mlich New(ptr, constructor), angelegt worden sind. Die Sourcecodereferenz deutet aber dann NICHT auf diese New-Anweisung, sondern auf die Zeile BEGIN im betreffenden Constructor. Wenn man diesen ausgemacht hat, muá man berlegen, wo Instanzen dieses Objekttyps angelegt werden und dort auf korrekte Freigaben prfen. Seite 11 - Wurde in einzelnen Diagnosezeilen das Flag "F" eingetragen ? Dieses Flag kommt nie allein. Es bedeutet (meistens), daá ein Deallo- kationsfehler passiert ist. Auáer dem "F" ist immer entweder ein "S" oder ein "M" gesetzt, was bedeutet, daá entweder eine Deallokation mit einer falschen Blockl„nge aufgerufen worden ist, bzw. daá der deallokierte Speicherblock an einer Adresse liegt, an der vorher keine Allokation vorgenommen worden ist. Solche Diagnosen sind entweder sehr schlimm oder sehr harmlos. Der harmlose Fall ist im Abschnitt "MemAllocSeg" beschrieben. Wenn diese Beschreibung nicht zutrifft, dann liegt wahrscheinlich ein echter Fehler vor, der unbedingt gefunden werden muá, weil er das gesamte Programm (auch den Heap Debugger) zum Absturz bringen kann. Letzteres kann passieren, wenn die Konsistenz der Heapverwaltung nicht mehr gegeben ist. In so einem Fall k”nnen brigens auch Daten auf dem Heap verstmmelt werden. ___ Auffinden von Bugs _________________________________________________ Wenn der Heap Debugger zu seinen Diagnosen Sourcecodereferenzen ausgeben konnte, dann ist das Auffinden von Bugs verh„ltnism„áig einfach. Wenn die Sourcecodereferenz allerdings mit "?" angegeben wird, dann be- findet sich die unter "Aufrufer" aufgefhrte Adresse in einem Modul, das nicht mit der Option "D+", also ohne Debuginformationen bersetzt worden ist. Oft ist der Aufrufer dann in der Run-Time-Library zu finden. Man sollte sich aber nicht zu dem Schluá verleiten lassen, daá man fr den entsprechenden Fehler dann gar nicht verantwortlich ist und daá die Run-Time-Library einen Bug hat. Wenn von Ihnen z.B. eine Allokation mittels "NewStr" (Funktion der Run-Time-Library) vorgenommen wurde, und der so angeforderte Heapspeicherblock wurde anschlieáend nicht korrekt mit DisposeStr deallokiert, dann liegt der Fehler in Ihrem Programmteil; als Aufrufer wird aber eine Zeile in der Funktion NewStr genannt. Viele Probleme dieser Art kann man l”sen, indem man die ganze Run-Time-Library mit Debug-Option neu bersetzt. Das ist nur bei BP7.0, nicht bei TP7.0 m”glich. Informationen hierzu bietet Borland in der Datei \BP\RTL\README. ___ Arbeiten mit einem externen Debugger _______________________________ In hartn„ckigen F„llen kann man versuchen, einen Fehler mit Hilfe des externen Debuggers einzugrenzen. Das ist besonders dann sinnvoll, wenn man dem Heap Debugger trotz aller Bemhungen keine Sourcecodereferenz entlocken kann. Im externen Debugger sollte man versuchen, auf die fragliche Programm- stelle (die Aufruferadresse) einen Breakpoint zu setzen. Beachten Sie hierzu den Unterschied zwischen der virtuellen und der aktuellen Segmentadresse, die der Heap Debugger ausgibt. Seite 12 Achtung: Die aktuelle Segmentadresse eines Aufrufers kann sich von Programmlauf zu Programmlauf verschieben. Nach dem Laden des Debuggers wird sie sich sogar sehr wahrscheindlich verschieben. Lassen Sie daher Ihr Programm mit geladenem Debugger einmal oder mehrmals laufen, ohne einen Breakpoint zu setzen. Verwenden sie die zuletzt ausgegebene aktuelle Segmentadresse, um den Breakpoint zu setzen. Sie setzen einen Breakpoint auf eine von Hand eingegebene Adresse mit der Funktion "Breakpoints->At...". Geben Sie einfach die Adresse ein und beginnen Sie die Segmentadresse UND die Offsetadresse jeweils mit "$" fr hexadezi- male Notation. Wenn Sie Ihr Programm dann starten und einen Breakpoint erreichen, versuchen Sie das Programm ab dieser Stelle in Einzelschritten fortzu- setzen, bis Sie zu einer Stelle des Programms kommen, die Ihnen bekannt ist. ___ Compilerschalter in USEHDEB ________________________________________ In die Unit UseHDeb wurden bereits einige Compilerschalter eingefhrt, die die Anpassung an besondere Anforderungen erleichtern sollen. Wir hoffen, daá damit die allermeisten Anpassungsprobleme zu l”sen sind, so daá dem Anwender eine weitergehende Ver„nderung des Sourcecodes erspart bleibt. Der Schalter "USE_SHAREWARE": Wenn dieser Schalter aktiv ist, dann wird der Heap Debugger in einer der Units "HDEB7S.TP?" benutzt. Wenn er ausgeschaltet ist, dann wird eine der Units "HDEB7F.TP?" eingebunden. Letztere stellt die Vollversion des Heap Debuggers dar und kann natrlich nur verwendet werden, wenn die Software registriert worden ist. Dieser Compiler ist bei Lieferung der Shareware- bzw. der Vollversion schon richtig eingestellt und muá also in der Regel nicht ver„ndert werden. Der Schalter "GERMAN_LANG": Wenn dieser Schalter aktiv ist, dann wird der Heap Debugger Report in deutscher Sprache ausgegeben, sonst in Englisch. Der Schalter "GETDEBUGINFO": Wenn dieser Schalter aktiv ist, dann wird bei der Reportausgabe ver- sucht, auf die Debug-Informationen im EXE-File zuzugreifen, um Dateina- men und Zeilennummer zu jeder Diagnosezeile zu ermitteln. Dieser Schal- ter sollte normalerweise aktiv bleiben. Der Schalter "REPORT_TO_FILE": Wenn dieser Schalter aktiv ist, dann wird die Reportausgabe der Unit UseHDeb in eine Datei umgeleitet. Der Name dieser Datei wird mit der Konstanten DumpFileName festgelegt und ist auf "HEAPDEB.DMP" voreinge- stellt, kann aber ver„ndert werden. Die Datei wird mit jeder Reportaus- gabe erweitert. Bitte beachten Sie: Wenn der Heap Debugger aus irgendei- nem Grund nicht initialisiert wurde und der Schalter "REPORT_TO_FILE" aktiviert ist, dann wird das Programm ohne Ausgabe einer Meldung (auch nicht in die Datei) mit dem Kommando "HALT" gestoppt. Seite 13 Der Schalter "SWITCH_TO_LASTMODE": Wenn dieser Schalter aktiv ist, dann wird vor der Reportausgabe der Unit UseHDeb mit dem Kommando "Textmode(LastMode)" in den Videomodus zurck- geschaltet, der beim Start des Programms aktiv war. Dies kann ntzlich sein, wenn das Hauptprogramm z.B. in einen vom BIOS nicht untersttzten Grafikmodus umschaltet oder Textfarben so manipuliert, daá die Report- ausgabe nicht lesbar ist. Dieser Schalter hat unter Windows keine Aus- wirkung. Beispiel fr das Ein- und Ausschalten eines Schalters: aktiv: "{$DEFINE GERMAN_LANG}" inaktiv: "{not $DEFINE GERMAN_LANG}" HEAP DEBUGGING IM DETAIL _______________________________________________ ___ Overlays ___________________________________________________________ Sie k”nnen den Heap Debugger auch innerhalb von Programmen nutzen, die von Overlayprogrammierung Gebrauch machen. Die Units USEHDEB und HDEB7? drfen allerdings nicht als Overlays geladen werden. ___ DLLs _______________________________________________________________ Eine DLL kann man mit dem Heap Debugger behandeln wie ein normales, ei- genst„ndiges Programm. Wenn ein Programm, das den Heap Debugger verwen- det, zur Laufzeit eine DLL einbindet, dann ist der Heap Debugger fr diese DLL nicht wirksam. Umgekehrt kann eine DLL den Heap Debugger ver- wenden, ohne daá dadurch die Heap-Operationen im Hauptprogramm berwacht werden. Wird sowohl in eine DLL alsauch in das Hauptprogramm der Heap Debugger eingebunden, so werden zum Programmende zwei Reporte ausgege- ben. Das Einbinden des Heap Debuggers in eine DLL erfolgt demgem„á auch wie bei einem normalen Programm: In der Hauptquelldatei der DLL (mit der šberschrift "library") wird die Unit UseHDeb als erste in die uses- Klausel eingefgt. Der Exit-Code der Unit UseHDeb (mit der Reportausgabe) wird beim Beenden der DLL durchgefhrt. Wann ist das ? Die DLL wird normalerweise beendet, wenn auch das Hauptprogramm, das die DLL geladen hat, beendet wird. Es gibt allerdings Ausnahmen. Wenn man das Hauptprogramm mit dem externen Debugger ausfhrt, so wird die DLL nicht bei Programmende abgeschlossen, sondern beim Verlassen des Debuggers, was dann aus unerfindlichen Grn- den h„ufig zu einem Absturz des Rechners fhrt. Es empfiehlt sich daher sehr, eine DLL, die den Heap Debugger einbindet, zur Laufzeit des Haupt- programms gezielt mit der Anweisung "FreeLibrary" zu beenden, wodurch der Exit-Code der Unit UseHDeb fr die DLL ausgefhrt und somit der Re- port ausgegeben wird. Das bisher Gesagte gilt fr DLLs unter DOS und unter Windows gleicher- maáen. Seite 14 Unter Windows ergibt sich aber noch ein zus„tzliches Problem: Die Re- portausgabe, die von der Unit UseHDeb unter Windows ja in ein WinCrt- Fenster vorgenommen wird, klappt bei einer DLL nicht: Die Folge des Ver- suches, eine Reportausgabe aus einer DLL heraus in ein WinCrt-Fenster vorzunehmen, ist in aller Regel entweder ein Laufzeitfehler oder das v”llige Ausbleiben jeder Ausgabe. Unter DOS gibt es diese Probleme nicht. Es ist unter Windows bei Einsatz des Heap Debuggers in einer DLL also unbedingt notwendig, die Ausgaben der Unit UseHDeb in eine Datei umzu- leiten. Hierfr wurde der Schalter "REPORT_TO_FILE" vorbereitet (siehe hierzu "Compilerschalter in USEHDEB"). ___ Programminstanzen (Windows) ________________________________________ Wenn unter Windows ein Programm, das den Heap Debugger einbindet, in mehreren Instanzen gestartet wird, so wird nur fr die erste Instanz der Heap Debugger installiert. Folgende Instanzen nutzen automatisch den schon installierten Heap Debugger mit. Die Ausgabe des Reports erfolgt erst nach Beenden der letzten aktiven Instanz des Programms, und der Re- port beinhaltet alle Heap-Operationen, die in anderen Instanzen des sel- ben Programms vorgenommen wurden, ohne das die verursachenden Instanzen in dem Report voneinander unterschieden werden k”nnen. Um die šbersicht- lichkeit zu wahren, sollten also m”glichst nicht mehrere Instanzen aus- gefhrt werden. ___ Interrupts ________________________________________________________ Der Heap Debugger ben”tigt fr seine Arbeit drei eigene Softwareinter- rupts. Das heiát, daá der Heap Debugger bei der Installation drei freie Interruptvektoren belegt und diese bei Programmende wieder restauriert. Der Heap Debugger sucht sich die freien Softwareinterrupts selbst aus, und zwar im Bereich 78h bis FFh. Aus diesem Bereich k”nnen gezielt ein- zelne Interrupts vom Programmierer ausgeschlossen werden, indem in der Unit UseHDeb.PAS die Anweisung "HeapDebInit([])" ver„ndert wird. In der als Parameter angegebenen leeren Menge kann eine Menge von Interruptnum- mern definiert werden, die vom Heap Debugger nicht benutzt werden sollen. Eine Žnderung dieses Aufrufes in "HeapDebInit([$F0..$FF])" wrde z.B. die Interruptvektoren F0h bis FFh fr die Benutzung durch den Heap Debugger ausschlieáen und somit fr das Hauptprogramm freihalten. ___ Stabilit„t und Performance _________________________________________ Wie schon erl„utert sollte der Heap Debugger nicht als Bestandteil fer- tiger Applikationen eingesetzt werden. Der Heap Debugger sollte aus- schlieálich als Debuggingwerkzeug in der Entwicklungsphase verwendet werden. Der permanente Einsatz des Heap Debuggers w„hrend der Softwareentwick- lung kann die Stabilit„t der entwickelten Software erheblich verbessern und die Entwicklungszeit verkrzen. Es ist jedoch nicht auszuschlieáen, daá der Heap Debugger in der Ent- wicklungsphase eine potentielle Ursache fr Programmabstrze sein kann, auch wenn dies von uns bisher nicht beobachtet werden konnte. Folgende Tatsachen sollten beachtet werden: Seite 15 - Der Heap Debugger berwacht nicht nur die korrekte Verwendung des Heapspeichers. Er ben”tigt auch selbst Heapspeicher fr diese Aufgabe. Wenn ein Programm zeitweise eine groáe Anzahl von Heapspeicherbl”cken allokiert, so kann der zus„tzliche Speicherbedarf des Heap Debuggers erheblich sein. Mit zus„tzlichen 24 Byte je allokiertem (und noch nicht wieder deallokiertem) Speicherblock sollte gerechnet werden. - Die Ausfhrung des Heap Debuggers erfordert zus„tzlich Platz auf dem Stack, und zwar sowohl bei der Ausfhrung von Speicheroperationen als- auch bei der Ausgabe der Reports in der Exitprozedur der Unit UseHDeb. Hier ist zu beachten, daá teilweise keine šberprfung des Stacks m”g- lich ist, so daá ein zu klein dimensionierter Stack ein Programm zum Absturz bringen kann. - Bei massiven Fehlern des Applikationsprogrammierers bei dem Umgang mit Heapspeicher kann der Einsatz des Heap Debuggers, der wie gesagt auch selbst mit Heapspeicher arbeitet, den Absturz eines Programmes sogar erst ausl”sen, was, in einer zuf„llig anderen Konstellation, ohne den Heap Debugger vielleicht nicht passiert w„re. Solche Abstrze k”nnen zum Beispiel dann passieren, wenn die Applikation versucht, einen vor- her gar nicht allokierten Speicherbereich freizugeben. In diesem Fall ist ein Programmabsturz als klares Indiz fr einen Programmierfehler jedenfalls einem trgerischen fehlerfreien Programmablauf vorzuziehen. - Der Heap Debugger braucht fr seine Arbeit zus„tzliche Rechenzeit. Je mehr Speicherbl”cke allokiert werden, um so mehr steigt der Zeitbedarf des Heap Debuggers, insbesondere beim Wiederfreigeben von Speicher. Diese Performanceeinbuáe wird aber allenfalls bei sehr zeitkritischen Anwendungen irgendwie sprbar sein. - Der Heap Debugger ben”tigt, wie schon im vorherigen Abschnitt erw„hnt, fr seine Arbeit drei freie Softwareinterrupts, deren Vektoren er zum Anfang des Programms auf eigene Routinen umlenkt und zum Ende des Pro- gramms wieder restauriert. Wenn ein Programm durch einen fatalen Feh- ler so abrupt beendet wird, daá die Exitprozedur von UseHDeb nicht mehr durchlaufen wird, dann werden auch diese Interruptvektoren nicht mehr wieder auf ihre alten Werte eingestellt. Wenn anschlieáend gela- dene Programme aber von korrekten Werten in diesen Vektoren abh„ngig sind, so kann dies zu Problemen fhren. Wenn sich solche Abstrze sehr h„ufig wiederholen, dann kann der Heap Debugger irgendwann keine freien Interrupts mehr finden und kann nicht gestartet werden. ___ Eingriffsm”glichkeiten fr den Programmierer _______________________ Es ist fr einige F„lle denkbar, daá ein Programmierer Žnderungen am Heap Debugger vornehmen m”chte, um z.B. die Reportausgabe seinen eigenen Vorstellungen anzupassen. Aus diesem Grunde wird die Unit UseHDeb im Quellcode mitgeliefert. Programm„nderungen drfen nur an dieser Unit und nur zu eigenen, nichtkommerziellen Zwecken vorgenommen werden. Darberhinaus bietet das Interface der Unit HDeb7?.TP? folgende typi- sierte Konstanten an, die zur Laufzeit eines Programms ver„ndert werden k”nnen: Seite 16 1) SuspendHeapdeb : Boolean = false; Wird diese Konstante zur Laufzeit des Hauptprogramms auf TRUE gesetzt, so werden anschlieáend keine Heap Operationen vom Heap Debugger mehr aufgezeichnet. Nach Rck„nderung des Wertes auf FALSE arbeitet der Heap Debugger wieder normal. Dies kann z.B. ntzlich sein, um quasi statische Allokationen, die sonst bei jeder Reportausgabe des Heap Debuggers auf- gefhrt werden, fr den Heap Debugger "unsichtbar" zu machen und dadurch einen "sauberen" Report zu erm”glichen. 2) RecordZeroSize : Boolean = false; Solange diese Konstante den Wert FALSE hat, werden Allokationen und De- allokationen mit der L„nge Null vom Heap Debugger ignoriert. Weil solche Operationen reine Sch”nheitsfehler sind und unseres Wissens keinen Scha- den anrichten k”nnen, ist diese Konstante auf FALSE voreingestellt. 3) RTEOnWrongSizedFree : Byte = 0; Wenn in diese Konstante ein anderer Wert als Null geladen wird, dann wird bei jeder Deallokation, die nicht die gleiche L„nge wie die zuge- h”rige Allokation aufweist (Flag "S"), sofort ein Run-Time-Error ausge- l”st. Die Nummer des Run-Time-Errors wird durch diese Konstante bestimmt. 4) RTEOnUnknownFree : Byte = 0; Wenn in diese Konstante ein anderer Wert als Null geladen wird, dann wird bei jeder Deallokation, zu der keine passende Allokation (gleiche Anfangsadresse des Heapspeicherblocks) gefunden werden kann (Flag "M"), sofort ein Run-Time-Error ausgel”st. Die Nummer des Run-Time-Errors wird durch diese Konstante bestimmt. BEKANNTE EINSCHRŽNKUNGEN UND PROBLEME __________________________________ ___ Mark/Release _______________________________________________________ Von der Verwendung der Befehle Mark und Release erh„lt der Heap Debugger keinerlei Kenntnis und kann sie also auch nicht bercksichtigen. Darber hinaus kann die Anweisung Release den Heap Debugger erheblich st”ren (bis hin zum Programmabsturz), weil dadurch eventuell auch Aufzeichnun- gen des Heap Debuggers verworfen werden, ohne daá der Heap Debugger die- ses erkennen kann. Allerdings werden die Befehle Mark und Release fast gar nicht mehr ver- wendet, denn sie bringen, unabh„ngig von der Unvertr„glichkeit mit dem Heap Debugger, noch eine Reihe anderer Probleme mit sich. Wahrscheinlich sind sie in der aktuellen Version des Compilers nur noch aus Kompatibi- lit„tsgrnden implementiert. Von der Verwendung von Mark und Release ist also allgemein abzuraten. Mark und Release stehen nur unter DOS zur Ver- fgung. Seite 17 ___ MemAllocSeg ________________________________________________________ Die Funktion MemAllocSeg in der Unit Memory (unter Windows: OMemory) stellt den Heap Debugger vor ein groáes Problem: Die Aufgabe dieser Funktion ist es, einen Heapspeicherbereich anzufordern, dessen Anfangs- adresse genau auf dem Anfang eines Speichersegmentes liegt, also die Offsetadresse 0000 hat. Um dieses zu erreichen, greift die Funktion MemAllocSeg tief in die Trickkiste, wobei wir zwischen den verschiedenen Zielplattformen unterscheiden mssen: Real Mode: Um garantiert einen Heapspeicherbereich mit der Offsetadresse 0000 allo- kieren zu k”nnen, reserviert die Funktion MemAllocSeg mittels GetMem zu- n„chst einen etwas gr”áeren Bereich, um anschlieáend sofort wieder einen kleinen Teil davon (n„mlich 8 Bytes), die entweder am Anfang oder am Ende des gerade allokierten gr”áeren Bereichs liegen, mittels FreeMem freizugeben. Hier wird also etwas getan, was zwar in engen Grenzen er- laubt, aber verp”nt ist: Der Heap Debugger "beobachtet" diese Operatio- nen und wird sie sp„ter in seinem Report ausgeben. Das kann dann z.B. so aussehen: program TEST; uses UseHDeb, Memory; var p: pointer; begin {...} p := MemAllocSeg(100); FreeMem(p, 100); end. HEAP-DEBUGGER-DIAGNOSE: 1 Pointer wurden registiert 3 Debug-Eintraege vorhanden auflisten (J/N) ? j Nr Pointer Size Flags Aufrufer Datei Zeile 1 1A4D:0000 112 S 020B[1438]:001F MEMORY.PAS 327 1A53:0008 8 F M 020B[1438]:00D5 MEMORY.PAS 355 1A4D:0000 100 FS 0000[122D]:003A TEST.PAS 7 Oder so: HEAP-DEBUGGER-DIAGNOSE: 1 Pointer wurden registiert 3 Debug-Eintraege vorhanden auflisten (J/N) ? j Nr Pointer Size Flags Aufrufer Datei Zeile 1 1531:0008 112 S 020C[0F1A]:001F MEMORY.PAS 327 1531:0008 8 FS 020C[0F1A]:00D5 MEMORY.PAS 355 1532:0000 100 F M 0000[0D0E]:004A TEST.PAS 7 Der Programmierer ist wohl oder bel gezwungen, solche nicht ganz ast- reinen Heap-Operationen zu dulden und derartige Diagnosen des Heap Debuggers zu ignorieren. Seite 18 (Die Referenz auf die Sourcecodestellen in der Unit Memory werden nur dann ausgegeben, wenn diese Unit mit der Option $D+ bersetzt worden ist.) Protected Mode (DOS/DPMI): Hier hat es die Funktion MemAllocSeg etwas einfacher als im Real Mode: Sie ruft einfach die Funktion "MemAllocateBlock" auf, welche von der RTM.EXE zur Verfgung gestellt wird und eine entsprechene DPMI-Funktion darstellt. Dadurch wird ein Heapspeicherblock allokiert, der garantiert bei der Offsetadresse 0000 beginnt. Wie schon im Abschnitt "Globaler und lokaler Heap" beschrieben, erh„lt der Heap Debugger von diesem Vorgang keine Kenntnis. Die Freigabe des so allokierten Heapspeicherblocks wird jedoch berlicherweise mit der Funktion FreeMem vorgenommen, wovon der Heap Debugger sehr wohl Kenntnis erh„lt. Das oben gezeigte TestProgramm wrde also im Protected Mode folgende Reportausgabe hervorrufen: HEAP-DEBUGGER-DIAGNOSE: 0 Pointer wurden registiert 1 Debug-Eintraege vorhanden auflisten (J/N) ? j Nr Pointer Size Flags Aufrufer Datei Zeile 059F:0000 100 F M 0001[0547]:003D TEST.PAS 7 Windows: Hier gilt das gleiche wie im Protected Mode unter DOS, nur daá sich die Funktion MemAllocSeg der Funktion "GlobalAlloc" bedient, um einen Heap- speicherbereich mit der Offsetadresse 0000 zu allokieren. Da es sich hier um eine Operation mit dem globalen Heap handelt, merkt der Heap Debugger davon nichts. Die Freigabe dieses Heapspeicherbereichs mittels FreeMem wird aber registiert. Die Konsequenz fr den Heap Debugger ist die gleiche wie im Protected Mode unter DOS. ___ BGI ________________________________________________________________ Bei der Initialisierung von BGI-Treibern tritt mitunter das bei "MemAllocSeg" beschriebene Problem auf. Vermutlich verwenden BGI-Treiber oder die Unit Graph eine eigene Implementation der Funktion "MemAllocSeg". ___ TMemoryStream ______________________________________________________ Dieser Stream benutzt in der Methode "ChangeListSize" die Funktion "MemAllocSeg", die weiter oben beschrieben ist. ___ Heapberlauf _______________________________________________________ Der Heap Debugger, der ja die Heap-Operationen eines Programms berwa- chen soll, ben”tigt fr seine Arbeit selbst ebenfalls Heapspeicher. Falls der Heap Debugger selbst keinen Heapspeicher mehr anfordern kann, weil dieser aufgebraucht ist, so wird bei der Reportausgabe ein Interner Fehler Nummer 203 gemeldet. Wenn das Hauptprogramm eine HeapError-Funk- tion definiert hat, dann kommt diese auch beim Scheitern einer Heapallo- kation innerhalb des Heap Debuggers zur Ausfhrung. Seite 19 ___ Programmabbruch ____________________________________________________ Wird ein Programm, das den Heap Debugger einbindet, abgebrochen, ohne daá die Exit-Prozedur der Unit UseHDeb (die den Report ausgibt) durch- laufen wird, so werden die von vom Heap Debugger ver„nderten Software- interrupts nicht restauriert und stehen danach - zumindest fr den Heap Debugger - nicht mehr als freie Interruptvektoren zur Verfgung. Nicht restaurierte Interruptvektoren, die sonst nirgens verwendet werden, stellen eigentlich kaum eine Gefahr dar, da diese Interrupts eigentlich von keinem Programm aufgerufen werden. Beim Neuinitialisieren des Heap Debuggers bei einem neuerlichen Programmstart werden aber wieder drei andere Interruptvektoren ausgesucht. Wenn sich die "harten" Abstrze wiederholen (ca. 40 mal), stehen irgendwann keine freien Interruptvekto- ren mehr zur Verfgung und der Heap Debugger kann nicht mehr initiali- siert werden, was sich nur durch einen Neustart des Rechners beheben l„át. ___ WINCRT _____________________________________________________________ Wenn das Hauptprogramm schon ein WinCrt-Fenster benutzt und dieses nicht mit DoneWinCrt geschlossen wird, bevor die Exit-Prozedur der Unit UseHDeb durchlaufen wird, dann bleiben typischerwiese 2000 Byte Heap- speicher allokiert, die dann im Heap Debugger Report aufgefhrt werden. Man sollte deswegen aber im Hauptprogramm kein DoneWinCrt-Kommando pro- grammieren, denn dies fhrt oft bei der Reportausgabe des Heap Debuggers zu neuen Problemen. Wie schon im Abschnitt "DLLs" beschrieben, kann der Heap Debugger bei der Einbindung in eine DLL keine Ausgabe in ein WinCrt-Fenster machen. In allen Zweifelsf„llen sollte man versuchen, auf die M”glichkeit der Reportausgabe in eine Datei auszuweichen.