

















                                     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


      EINFHRUNG

      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 fehlschlgt ................................  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
      Stabilitt und Performance .......................................... 14
      Eingriffsmglichkeiten fr den Programmierer ........................ 15


      BEKANNTE EINSCHRNKUNGEN UND PROBLEME

      Mark/Release ........................................................ 16
      MemAllocSeg ......................................................... 17
      BGI ................................................................. 18
      TMemoryStream ....................................................... 18
      Heapberlauf ........................................................ 18
      Programmabbruch ..................................................... 19
      WINCRT .............................................................. 19

      Seite 3


      EINFHRUNG _____________________________________________________________

      ___ 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
      whrend der Entwicklungsphase in sein Programm einbindet, wird nach je-
      dem Programmabschlu auf briggebliebene Speicherblcke 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 spter 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
      angehngt 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 Heapspeicherblcke und sonstige fehler-
      hafte Heap-Operationen werden im Heap Debugger Report ausgegeben.


      ___ Was der Heap Debugger NICHT kann ___________________________________

      Folgende Heap-Operationen knnen 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 nmlich 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 vlligen 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 Erklrung 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 bentigt. Solche Variablen (bzw.
      Strukturen oder Objekte) knnte der Pogrammierer auch im Datensegment
      (als globale Variablen) allokierten, aber da die Gre des Datensegmen-
      tes auf insgesamt 64KB beschrnkt ist, wird manchmal der Heap als Aus-
      weg gewhlt. Wenn solche (nur einmalig allokierten) quasi-statischen
      Variablen nicht wieder freigegeben werden, so ist dies nur ein Schn-
      heitsfehler, hat aber sonst keine Konsequenzen. Der Heap Debugger be-
      mngelt 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 Lnge
      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 verlt, knnen 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 Lschen
      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 enthlt 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
      beschrnkt: Die Sharewareversion des Heap Debuggers verfolgt nur die
      ersten 50 Allokationen von Heapspeicherblcken. 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 zugnglich gemacht werden.


      ___ Lizenzbedingungen __________________________________________________

      Wer den Heap Debugger in der unbeschrnkten Vollversion nutzen mchte,
      mu eine Registrierung bei den Autoren vornehmen und erhlt im Zuge der
      Lieferung der Vollversion eine Lizenz zur Nutzung der Vollversion auf
      einem einzelnen Arbeitsplatz.

      Bei Nutzung des Heap Debuggers auf mehreren Arbeitspltzen 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 Verffentlichung ausfhrlich getes-
      tet haben, knnen wir keine Garantie fr einwandfreie Funktion oder Feh-
      lerfreiheit dieser Software bernehmen.

      Wir empfehlen die Nutzung des Heap Debuggers whrend 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 zustzlichen Gefahren fr die Stabilitt einer Soft-
      ware, die den Heap Debugger einbindet, hin. Nheres hierzu siehe Ab-
      schnitt "Stabilitt und Performance".

      Bei Lieferungen dieser Software erstreckt sich unsere Garantie aus-
      schlielich auf die Lesbarkeit des gelieferten Datentrgers. Wir ber-
      nehmen keinerlei Haftung fr Schden, 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 mglichst 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 erhlt 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 knnte
      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 auerdem die Einstellungen
      "Link-Puffer: Festplatte" und "Externer Debugger" bentigt. Unter Win-
      dows heit die letzte Option "Debug-Info in EXE".

      "Unit-Verzeichnis: \BP\RTL\WIN" (DOS/DPMI und Windows):

      Die Unit UseHDeb bentigt im Protected Mode (DOS+Windows) die Unit
      WINPROCS. Diese befindet sich gewhnlich 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 ergnzen.


      ___ Wenn die Initialisierung fehlschlgt _______________________________

      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 bentigt drei freie Interrupts. In diesem
          Falle ist wahrscheinlich unsere Testmethode zum Finden
          freier Interrupts verantwortlich. Es kommt selten vor,
          da tatschlich 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 zunchst, 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 (mglichst 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 enthlt 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 Gre des allokierten bzw. deallokieren Blocks
            ausgegeben.
      (*6): Die hier ausgegebenen Flags haben folgende Bedeutung
            (Kombinationen sind mglich):

            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-
                   lnge (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 heit, 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 abhngig 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 knnen im Heap Debugger Report in Ausnahmefllen 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 zustzliche, 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 knnen.

      "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 whrend der gesamten Entwicklungszeit
      einer Applikation kontinuierlich eingesetzt wird, dann lt sich eine
      nach einem Testlauf pltzlich auftauchende andere Meldung meist sehr
      leicht mit der zuletzt vorgenommenen Programmnderung in Zusammenhang
      bringen.

      Wenn die Sache einmal nicht so einfach ist, mu man die Diagnose des
      Heap Debuggers zunchst einmal interpretieren, um dem Problem auf die
      Schliche zu kommen.

      Hierzu sollte man sich die folgenden Fragen stellen:

      - Ist die Anzahl der Diagnoseeintrge immer gleich oder variiert diese
        Anzahl ?

        Soweit die Anzahl nicht variiert, handelt es sich offenbar um
        einmalig vorkommende Fehler im Programm. Es gibt Flle, bei denen
        die Bezeichnung Fehler sogar etwas zu scharf gewhlt ist. Manche
        Programme legen nmlich quasi-statische Variablen auf dem Heap an,
        und geben diese dann am Ende nicht wieder frei. So ein Verhalten
        ist zwar nicht sonderlich schn und sollte deshalb vermieden werden;
        es hat andererseits aber auch keine schlimmen Konsequenzen.

      - Lt sich das Anwachsen der Anzahl der Diagnosezeilen mit einer
        bestimmten Funktion meines Programms in Zusammenhang bringen ?

        Wenn die Anzahl wchst, dann sollte man versuchen, den sich
        offenbar wiederholenden Fehler auszumachen. Meistens ist das sehr
        einfach, wenn nmlich der Heap Debugger fr mehrere Eintrge die
        selbe Aufruferadresse ausgibt. Es handelt sich dann wohl um einen
        Fehler, der immer dann zum Tragen kommt, wenn eine bestimmte
        Programmfunktion ausgelst wird. Solche Fehler sollte man auf jeden
        Fall beseitigen, da sie den gefrchteten "Gedchtnisschwund" auslsen.

      - Wurde in einzelnen Diagnosezeilen irgendein Flag eingetragen ?

        Soweit nicht, handelt es sich bei den Diagnosen des Heap
        Debuggers um Hinweise auf "klassische" Fehler, nmlich auf das
        unterlassene Freigeben "normaler" Heapspeicherblcke, 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, nmlich
        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. Auer dem "F" ist immer entweder ein
        "S" oder ein "M" gesetzt, was bedeutet, da entweder eine Deallokation
        mit einer falschen Blocklnge 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 knnen 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 verhltnismig 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 anschlieend 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 lsen, indem man die ganze
      Run-Time-Library mit Debug-Option neu bersetzt. Das ist nur bei
      BP7.0, nicht bei TP7.0 mglich. Informationen hierzu bietet Borland
      in der Datei \BP\RTL\README.


      ___ Arbeiten mit einem externen Debugger _______________________________

      In hartnckigen Fllen 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 lsen sind, so
      da dem Anwender eine weitergehende Vernderung 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 verndert 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 verndert 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 knnen 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-
      genstndiges 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 hufig 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-
      maen.

      Seite 14


      Unter Windows ergibt sich aber noch ein zustzliches 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
      vllige 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 knnen. Um die bersicht-
      lichkeit zu wahren, sollten also mglichst nicht mehrere Instanzen aus-
      gefhrt werden.


      ___ Interrupts ________________________________________________________

      Der Heap Debugger bentigt fr seine Arbeit drei eigene Softwareinter-
      rupts. Das heit, 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 knnen gezielt ein-
      zelne Interrupts vom Programmierer ausgeschlossen werden, indem in der
      Unit UseHDeb.PAS die Anweisung "HeapDebInit([])" verndert 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 ausschlieen und somit fr das Hauptprogramm freihalten.


      ___ Stabilitt und Performance _________________________________________

      Wie schon erlutert sollte der Heap Debugger nicht als Bestandteil fer-
      tiger Applikationen eingesetzt werden. Der Heap Debugger sollte aus-
      schlielich als Debuggingwerkzeug in der Entwicklungsphase verwendet
      werden.

      Der permanente Einsatz des Heap Debuggers whrend der Softwareentwick-
      lung kann die Stabilitt der entwickelten Software erheblich verbessern
      und die Entwicklungszeit verkrzen.

      Es ist jedoch nicht auszuschlieen, 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 bentigt auch selbst Heapspeicher fr diese Aufgabe.
        Wenn ein Programm zeitweise eine groe Anzahl von Heapspeicherblcken
        allokiert, so kann der zustzliche Speicherbedarf des Heap Debuggers
        erheblich sein. Mit zustzlichen 24 Byte je allokiertem (und noch
        nicht wieder deallokiertem) Speicherblock sollte gerechnet werden.
      - Die Ausfhrung des Heap Debuggers erfordert zustzlich 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 mg-
        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 auslsen, was, in einer zufllig anderen Konstellation, ohne den
        Heap Debugger vielleicht nicht passiert wre. Solche Abstrze knnen
        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 zustzliche Rechenzeit. Je
        mehr Speicherblcke allokiert werden, um so mehr steigt der Zeitbedarf
        des Heap Debuggers, insbesondere beim Wiederfreigeben von Speicher.
        Diese Performanceeinbue wird aber allenfalls bei sehr zeitkritischen
        Anwendungen irgendwie sprbar sein.
      - Der Heap Debugger bentigt, wie schon im vorherigen Abschnitt erwhnt,
        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 anschlieend gela-
        dene Programme aber von korrekten Werten in diesen Vektoren abhngig
        sind, so kann dies zu Problemen fhren. Wenn sich solche Abstrze sehr
        hufig wiederholen, dann kann der Heap Debugger irgendwann keine
        freien Interrupts mehr finden und kann nicht gestartet werden.


      ___ Eingriffsmglichkeiten fr den Programmierer _______________________

      Es ist fr einige Flle denkbar, da ein Programmierer nderungen am
      Heap Debugger vornehmen mchte, um z.B. die Reportausgabe seinen eigenen
      Vorstellungen anzupassen. Aus diesem Grunde wird die Unit UseHDeb im
      Quellcode mitgeliefert. Programmnderungen 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 verndert werden
      knnen:

      Seite 16


      1)   SuspendHeapdeb : Boolean = false;

      Wird diese Konstante zur Laufzeit des Hauptprogramms auf TRUE gesetzt,
      so werden anschlieend keine Heap Operationen vom Heap Debugger mehr
      aufgezeichnet. Nach Rcknderung 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 ermglichen.

      2)   RecordZeroSize : Boolean = false;

      Solange diese Konstante den Wert FALSE hat, werden Allokationen und De-
      allokationen mit der Lnge Null vom Heap Debugger ignoriert. Weil solche
      Operationen reine Schnheitsfehler sind und unseres Wissens keinen Scha-
      den anrichten knnen, 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 Lnge wie die zuge-
      hrige Allokation aufweist (Flag "S"), sofort ein Run-Time-Error ausge-
      lst. 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 ausgelst. Die Nummer des Run-Time-Errors wird
      durch diese Konstante bestimmt.


      BEKANNTE EINSCHRNKUNGEN UND PROBLEME __________________________________

      ___ Mark/Release _______________________________________________________

      Von der Verwendung der Befehle Mark und Release erhlt der Heap Debugger
      keinerlei Kenntnis und kann sie also auch nicht bercksichtigen. Darber
      hinaus kann die Anweisung Release den Heap Debugger erheblich stren
      (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, unabhngig von der Unvertrglichkeit mit dem
      Heap Debugger, noch eine Reihe anderer Probleme mit sich. Wahrscheinlich
      sind sie in der aktuellen Version des Compilers nur noch aus Kompatibi-
      littsgrnden 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 groes 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 knnen, reserviert die Funktion MemAllocSeg mittels GetMem zu-
      nchst einen etwas greren Bereich, um anschlieend sofort wieder einen
      kleinen Teil davon (nmlich 8 Bytes), die entweder am Anfang oder am
      Ende des gerade allokierten greren Bereichs liegen, mittels FreeMem
      freizugeben. Hier wird also etwas getan, was zwar in engen Grenzen er-
      laubt, aber verpnt ist: Der Heap Debugger "beobachtet" diese Operatio-
      nen und wird sie spter 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, erhlt 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 erhlt. 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, bentigt 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 vernderten 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
      lt.


      ___ 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 Zweifelsfllen sollte man versuchen, auf die Mglichkeit der
      Reportausgabe in eine Datei auszuweichen.

