

















                                     The

                              HEAP DEBUGGER V2.0

                                     for
                             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






                                        CONTENTS


      INTRUDUCTION

      Why Heap Debugging ? ................................................  3
      What the Heap Debugger CAN do........................................  3
      What the Heap Debugger CANNOT do ....................................  3
      The usage of Dynamic Memory .........................................  3
      Versions and Targetplatforms ........................................  4
      List of the Files ...................................................  5
      Shareware Concept ...................................................  5
      Licence Conditions ..................................................  5
      Usertips and Warranty Limitation ....................................  6

      USING THE HEAP DEBUGGER

      Linking the Heap Debugger ...........................................  6
      Compiler- and Linkeradjustments .....................................  6
      When the Initialization fails .......................................  7
      The Heap Debugger Report ............................................  7
      Special Messages in the Heap Debugger Report ........................  9
      Interpretation of the Report ......................................... 9
      Hunting for Bugs .................................................... 10
      Working with the External Debugger .................................. 11
      Compilerswitches in USEHDEB ......................................... 11


      HEAP DEBUGGING IN DETAIL

      Overlays ............................................................ 12
      DLLs ................................................................ 12
      Program instances (Windows) ......................................... 13
      Interrupts .......................................................... 13
      Stability and Performance ........................................... 13
      Intervention possibilities for the Programmer ....................... 14


      KNOWN LIMITATIONS AND PROBLEMS

      Mark/Release ........................................................ 15
      MemAllocSeg ......................................................... 15
      BGI ................................................................. 16
      TMemoryStream ....................................................... 16
      Heap Overrun ........................................................ 17
      Program Halt ........................................................ 17
      WINCRT .............................................................. 17

      Page 3


      INTRODUCTION____________________________________________________________

      ___ Why Heap Debugging ? _______________________________________________

      The Heap Debugger controls (nearly) all by the program preformed heap
      operations and writes among other things a list of all heap memory
      areas that were not released. The programmer, who uses the Heap Debug-
      ger while developing his program, will be notified about the remaining
      Memoryblocks after every ending of his program.

      The Heap Debugger makes the finding of mistakes extremely easy, because
      it gives (often) a note about the source code location (file name and
      line number), where incorrect heap operations were preformed, or where
      a not released memory block was allocated.

      Herefor the Heap Debugger uses the debug information for the external
      Debugger, that (optionally) the is created by the compiler and that
      extends the EXE-files.


      ___ What the Heap Debugger CAN do ______________________________________

      The Heap Debugger controls all allocations of meap memory, that are
      performed with the commands

         - GetMem
         - New
         - FreeMem
         - Dispose

      Also calls of these routines from within the runtime-library and from
      program-parts, that are not available in sourcecode (for example
      foreign TPU's) are considered.

      All non correct deallocated heap memory blocks and other false heap
      operations are listed in the Heap Debugger Report.


      ___ What the Heap Debugger CANNOT do ___________________________________

      The following heap operations cannot be controlled by the Heap Debugger:

         - Mark and Release (are not allowed to be used !)

         - direct access to the global heap (DPMI+Windows),
           so all "Global..."-calls

         - direct access to the local heap (Windows),
           so all "Local..."-calls


      ___ The Usage of Dynamic Memory _______________________________________

      In programs, that uses heap memory intensively, not seldom treacherous
      programming errors are made: when dynamicly requested memory blocks
      are not released correctly, the available heap memory stepwise
      shrinks all together, so that sometime for a new request not enough
      space remains and the program may stop or collapse.

      Page 4


      It only comes to a complete consumption of the heap memory, when
      allocations without deallocating, not only once, but again and again
      are preformed. Such allocations could work a few hundret times until the
      whole heap memory is used up. So such crashes will normally happen later
      to the user, who of course does not know why.

      There are also allocations, that only once, so for instance in the
      initialg process are done, because the program uses heap memory space
      for quasi-static variables. The programmer could allocate such variables
      (respectively structures or objects) into the data segment (as global
      variables), but since the size of the data segment is limited to
      a total of 64KB, he will sometimes misuse the Heap as a way out. When
      such (only once allocated) quasi-static variables are not released, then
      this is only a disfigurement, and has no other consequences. The Heap
      Debugger criticizes of course also such offences.

      Particularly treacherous are deallocation errors, that means incorrect
      released memory. A deallocation error is when with the releasing of
      heap memory a false address or a false length is directed, so to the
      undertaken deallocation no allocation was processed before. Since the
      runtime-library mostly relies upon the information the programmer gives,
      deallocation errors can have disastrous consequences.

      Especially the object oriented programming makes intensively use of heap
      memory. For every new dynamic instance of an object type there will be a
      heap allocated for the fields of the object, that when deleting then
      object instance must be released. Herefor you use the commands NEW and
      DISPOSE in the for OOP-use extended syntax. Also forgotten objects
      consume heap memory.


      ___ Versions and Targetplatforms _______________________________________

      The Heap Debugger was developed and tested with

                  Borland Pascal V7.0 and V7.01

                  with the target systems
                  - Real Mode (for this HDEB7?.TPU)
                  - Protected Mode (for this HDEB7?.TPP)
                  - Windows (for this HDEB7?.TPW)

                  under
                  - DOS 6.2x
                  - Windows V3.1
                  - Windows for Workgroups V3.11
                  - Windows NT 3.5 Workstation
                  - OS/2 V2.11.

      A Version for Delphi V1.0 for Windows is be prepared.

      Page 5


      ___ List of the Files __________________________________________________

      USEHDEB.PAS .... Unit to link to your pascal program, for
                       DOS, DOS/DPMI and WINDOWS
      HDEB7S.TPU ..... The core of the Heap Debugger,
                       shareware version, for DOS/Real Mode
      HDEB7S.TPP ..... The core of the Heap Debugger,
                       shareware version, for DOS/Protected Mode
      HDEB7S.TPW ..... The core of the Heap Debugger,
                       shareware version, for Windows
      HDEB7F.TPU ..... The core of the Heap Debugger,
                       registered version, for DOS/Real Mode
      HDEB7F.TPP ..... The core of the Heap Debugger,
                       registered version, for DOS/Protected Mode
      HDEB7F.TPW ..... The core of the Heap Debugger,
                       registered version, for Windows
      VIEWME.EXE ..... The Heap Debugger in pictures (sliteshow, req. VGA)
      README.TXT ..... This text (english)
      LIESMICH.TXT ... This text (german, in mare correct grammer!)
      DIZFILES.ZIP ... Short description-files, for Sysops
      SHARWARE.ZIP ... This file only conmes with registered versions and
                       contains the sharewareversion
      BESTELL.TXT .... Orderform (german)
      ORDER.TXT ...... Orderform (english)


      ___ Shareware Concept __________________________________________________

      The Heap Debugger is Shareware, not Public Domain or Freeware!

      The through the shareware distributers delivered version of the Heap
      Debugger with the files HDEB7S.* ("S"=Shareware) and the accompanied
      files and the file USEHDEB.PAS are allowed to be used for test purposes
      and are allowed to be distributed freely.

      The shareware version is towards the registered version in its capacity
      limited: The shareware version of the Heap Debugger controls only the
      first 50 allocations of memory blocks. All following allocations will be
      ignored. When exceeding the shareware limit there will come an
      appropriate message in the report (at the end of the program).

      Registered versions of the Heap Debuggers contain the files HDEB7F.*
      ("F"=Full). These files are not allowed to be distributed to third, or
      to be made available for them.


      ___ Licence Conditions _________________________________________________

      If you want to use the Heap Debugger in the unlimited version, you have
      to register. With the delivery of the software you will receive a
      licence for the usage on a single workstation.

      If you want to use the Heap Debugger on several workstations then you
      have to register for every Workstation. Herefor we offer cheaper prices.

      A registration form is in the file ORDER.TXT prepared.

      Distribution of the registered version of the Heap Debugger is absolutely
      prohibited. Especially the files HDEB7F.* must not be delivered to
      thirds.

      Page 6


      ___ Usertips and Warranty Limitations __________________________________

      Although we tested the Heap Debugger in detail before publishing, we
      cannot give a guarantee for error-free function of this software.

      We suggest the usage of the Heap Debugger only during the developing
      phase.

      The Heap Debugger shall help you in your software development to avoid
      errors with the memory managment or delete them. We point to the
      additional dangers of the stability of a software, that involves the
      Heap Debugger. More information is given in the section "Stability and
      Performance".

      For registered versions of the Heap Debugger we warrant the physical
      media to be readable. We specifically disclaim all other warranties!


      Using the Heap Debugger ________________________________________________

      ___ Linking the Heap Debugger __________________________________________

      To link the Heap Debugger into your program, you only have to insert
      the unit UseHDeb in the uses-clause of your main program. For Example:


            PROGRAM MyProg;

               UseHDeb,
                \  /
                 \/
            USES   Drivers, Objects, Views, Menus, ...

      It is a good idea, to list the Unit UseHDeb as the first Unit in the
      uses-clause. The initialization of the Heap Debugger is done by the
      initialization-section of this Unit. After the initialization the Heap
      Debugger can "watch" heap operations. That is why the initialization
      of UseHDeb should be done before other Units, that possibly already
      preform heap operations.


      ___ Compiler- and Linkeradjustments __________________________________

      "D+":

      The Heap Debugger will only be initialized when the Unit UseHDeb is
      compiled with the option "D+" (debug-informations on). This is caused
      by, that almost the whole Unit UseHDeb is excepted from the compilation
      with the clause {$IFOPT D+}...{$ENDIF} otherwise. So this switch can be
      used to turn the Heap Debugger on and off, alltho theoretic the Heap
      Debugger could work without the D+ being turned on.

      All other Units, that are integrated in your program and also the main
      program need to be compiled with the option D+ turned on, if you want
      the to get source code references within the report.

      Page 7


      "Link-Buffer: Disk" and "Standalone Debugging":

      Beside the compiler option D+ the adjustments "Link-Buffer: Disk" and
      "Standalone Debugger" are also required. Under Windows the last option
      is called "Debug-Info in EXE".

      "Unit-Directories: \BP\RTL\WIN" (DOS/DPMI and Windows):

      The Unit UseHDeb needs in the protected mode (DOS+Windows) the Unit
      WINPROCS. This is found normally in the directory "\BP\RTL\WIN". Since
      under DOS this index is normally not adjusted as a Unit-Directory (see
      Options-->Directories), you must add this directory to the list of
      unit-directories yourself.


      ___ When the Initialization fails ______________________________________

      The initialization of the Heap Debugger is done through the initiali-
      zation section of the unit UseHDeb. When it fails the UseHDeb reports
      "Unable to initialize the Heap Debugger !" and stops the program with
      the command HALT.

      The failing of the Initialization can have following reasons:

        - You are using a modified runtime-library, that in a for
          the Heap Debugger important point does not match with the
          original from Borland.
        - You are using an operating system or a special tool (e.g.
          memory management tool) that wasn't verified to supported.
        - You are using an unsupported compiler version.
        - There were no free interrupt vectors found. The Heap Debugger
          needs three free interrupts. In this case probably our
          test method for finding free interrupts did fail. It is
          extremely rare that all interrupts are really used.
        - The Heap Debugger is already initialized. This should not
          happen when you use the Unit UseHDeb.

      When in your system the initialization fails, then please try to run
      your program within a tested configuration (for instance: MSDOS 6.2 ,
      Windows 3.1) without loading any special memory managers or multi-
      taskers. Observe if the Heap Debugger can now be initialized in this
      configuration.

      Please inform us about configuration in, with that the Heap Debugger
      could not be used. (if possible per email)


      ___ The Heap Debugger Report ___________________________________________

      The Heap Debugger gives a report when ending a program. This happens in
      the exit-procedure of the unit UseHDeb.

      The Heap Debugger Report has normally the following structure
      (for example:)

      Page 8


        HEAP DEBUGGER DIAGNOSIS:
        2 pointer were registered (*1)
        1 debug-entries available (*2)
        list (Y/N) ? y

        (*3)  (*4)      (*5)  (*6)           (*7)       |------(*8)------|
        No    Pointer   Size  Flags            Caller          File   Line
         2  1A41:0000    256          0000[122D]:0044   HEAPBUG.PAS     16


      (*1): Here is printed, how many heap allocations the Heap Debugger did
            observe in total. This number means no statement about possible
            mistakes.
      (*2): Here is printed, how many diagnosis lines the Heap Debugger has
            available to dump. In the best case this number should always
            be "0". Not all but most of the diagnosis lines point towards a
            programming error.
      (*3): Here is a sequential counter of all in the program done
            allocations. With deallocations (Flag "F") this place is empty.
      (*4): Here is the addresses of the allocated respectively deallocated
            heap memory block printed. This address can vary from program-run
            to program-run.
      (*5): Here is the size of the allocated respectively deallocated block
            printed.
      (*6): The here listed Flags have following meanings
            (combinations are possible):

            none : Its about an allocation, to that no fitting deallocation
                   was performed.
            "O"  : Its about an instance-data of an object type. This is the
                   data area, that is created by the constructor of a object
                   with every new instance. As caller is the line with the
                   word "BEGIN" in the costructor given (the line with the
                   word "END" in the destructor at deallocations).
            "F"  : This diagnosis line deals with a deallocation (F=free).
                   What went wrong with this deallocation is explained in one
                   of the following flags.
            "S"  : A heap memory block was not in the same blocklength
                   (S=size) deallocated, with which it was allocated. In this
                   case, the flag will appear both in the diagnosis lines of
                   the allocation and of the deallocation.
            "M"  : To a deallocation there was not a fitting allocation found
                   (M=mismatch). This means, it was tried, to deallocate a
                   heap memory block, who's address was not registered by a
                   previous allocation. This flag appears only together with
                   the flag "F".

      (*7): At this address the heap operation, that this diagnosis line is
            about, was called. The segment address is the virtual segment
            address and in brackets "[]" the actual segment address. The
            virtual segment address is generated by the linker and is the
            address relative to the address 0000. The actual segment address
            will be given when loading a program and depends on the location,
            at which the program is loaded into memory. The virtual address
            can be found in the map-file. The actual address can vary from
            program-run to program-run.

      Page 9


      (*8): Here the sourcecode location (file name and line number) ist
            shown according to the caller address. It is required that the
            debug information exist in the EXE-file. If there are no debug
            informations present "No Info" will be printed here. If there
            are debug informations present but the sourcecode-line of the
            caller address couldn't be found nonetheless, a "?" will be
            printed here.


      ___ Special Messages in the Heap Debugger Report _______________________

      The following messages can appear under special circumstances:

      "Program stopped by HALT(nnn)"

      This message says, that the program was stopped with the command
      HALT(nnn). The Exitcode is given with nnn.

      "runtime-error nnn at ssss:oooo, file: ________ line: ______"

      When the program is stopped through a runtime error, this message will
      be present. As additional, useful information the file name and line
      number of the error are printed, if this information is available.

      "internal error 203 occured in Heap Debugger"

      This message means, that the Heap Debugger did not have enough heap
      memory to record all heap operations.

      "Shareware-limit exceeded!
       Only 50 pointers were registered!"

      This message will only be printed in the shareware version and tells us
      that the shareware limit of 50 controlled allocations was exceeded
      during the runtime.


      ___ Interpretation of the Report _______________________________________

      Of course you should attempt to receive the message "0 debug-entries
      available", at the end of a program-run. If the Heap Debugger is
      continually in action during the development of a application, then an
      possibly reported bugs can easly be found, because the error most often
      was made during the last changes to the program.

      If the matter isn't so easy, then you first need to understand the
      diagnosis of the Heap Debugger, to solve the problem.

      For this purpose you need to ask yourself following questions:

      - Is the number of the diagnosis entries always the same, or does this
        number vary?

        As far as the number does not vary, then it must have to do with an
        error that happens only once a program-run. There are cases, in that
        the name error is to strong. Some programs allocate some quasi-static
        variables on the Heap, and don't release them at the end. This behavior
        is not very nice and should be tried to be avoided; on the other hand
        this has no bad consequences.

      Page 10


      - Can the increase of the number of diagnosis lines have to do with
        certain functions of my program?

        If the number grows, then you should try to find the obviously
        repeated error. Most often this is very easy, when the Heap Debugger
        gives for several entries the same caller address. It then appears to
        be a error, that always occurs when a certain program function is
        executed. You should always get rid of these errors, because they can
        cause "loss of memory".

      - Are there any Flags in a diagnosis lines?

        If not, then this diagnosis denunciats a "classic" error, particulary
        a not released "normal" heap memory block, that was allocated with
        GetMem or New. The sourcecode reference refers to the location, were
        this demand happened.

      - Is the Flag "O" present ?

        If yes, the Heap Debugger shows an error in relation to an object.
        If there is just an "O" entered, then this has to with a not released
        dynamic instance of an object, which was set up with the command new
        in the OOP-variation. The sourcecode reference does NOT point to this
        New-command, but to the line BEGIN in the concerned constructor. If
        you found out this, you need to think about where the instances of
        this object type is allocated and to and check for the correct
        releasement.

      - Is th Flag "F" present ?

        This flag appears never alone. It means (mostly), that a deallocation
        error has occurred. Beside the "F" there will always be a "S" or a
        "M", which means, that either a deallocation with a false block length
        was called, or that the deallocated memory block has an address,
        where no allocation was done.

        This diagnosis is either real bad or harmless. The harmless case
        is described in the section "MemAllocSeg". If this description doesn't
        prove, then there is probably a REAL error, that has to be found,
        because it could cause the whole program (also the Heap Debugger) to
        crash. This can happen, if the consistency of the heap management
        becomes damaged.


      ___ Hunting for Bugs ___________________________________________________

      If the Heap Debugger gives with his diagnosis sourcecode references,
      then is the finding of bugs relatively easy.

      If instead of a sourcecode reference a "?" is printed, then the under
      "Caller" listed address is in an module, that has not debug informations
      because is wasn't compiled with the option "D+". Often you can find the
      caller in the runtime-library.

      You should not let yourself come to the conclusion, that you are not
      responsible for the error and that the runtime-library has a Bug. If you
      for instance do an allocation with "NewStr" (function of the runtime

      Page 11


      library) and the requested heap memory block then is not deallocated
      afterwards with DisposeStr, then the error is in your program. But the
      caller is a line in the function NewStr in the runtime library.

      A lot of these problems can be solved, if you recompile the whole run-
      time-library with the debug-option. This is only possible with BP7.0
      (not with TP7.0). Informations for this you find in Borland's
      \BP\RTL\README.


      ___ Working with the External Debugger _________________________________

      In hard cases you should try to find an error with the help of the
      external debugger. That makes sense when the Heap Debugger did not
      give sourcecode references.

      In the external Debugger you should set a breakpoint at the callers
      address.

      Please notice the difference between the virtual and the actual
      segment address, that the Heap Debugger prints.

      Attention: The actual segment address of the caller can vary from
      program-run to program-run. After loading the Debugger it will mostly
      move. Let your program run once or a few times with the loaded debugger
      before you set a breakpoint. Use the last given actual segment address.
      You can set a breakpoint at any adress function "Breakpoints-At...".
      Just enter the caller address and start the segment address AND the
      offsetaddress with a "$" for hexadecimal notation.

      When you reach a breakpoint, continue the execution stepwise until you
      reach an area that you know.


      ___ Compilerswitches in USEHDEB ________________________________________

      In the Unit UseHDeb there are already a few compiler switches established,
      that eases the adjustment. We hope, that the most adjustment problems can
      be solved, so that you don't need to change the source code.

      The Switch "USE_SHAREWARE":

      When this switch is defined, the Heap Debugger uses the unit
      "HDEB7S.TP?". When it is undefined, then the Units "HDEB7F.TP?" is
      integrated. This stands for the registered version of the Heap Debugger
      and can of course only be used, if the software was registered. This
      switch is correctly adjusted in the delivered shareware or the
      registered version and does normally not need to be changed.

      The Switch "GERMAN_LANG":

      When this switch is defined, the Heap Debugger Report will be given in
      german language instead of english.

      Page 12


      The Switch "GETDEBUGINFO":

      When this switch is defined, then the Heap Debugger will try to access
      to the debug informations in the EXE-file to find out the file name and
      line number for every diagnosis line. This switch should normally stay
      active.

      The Switch "REPORT_TO_FILE":

      When this switch is defined, then the report output will be transferred
      into a file. The name of this file in defined in the constant
      "DumpFileName" and that is preadjusted to "HEAPDEB.DMP" but can be
      changed. The file will be enlarged with every report output. Please
      note: When the Heap Debugger because of any reason cannot be initialized
      and the switch "REPORT_TO_FILE" is active, then the program will be
      stopped with the command "HALT" without any warning (also in the file).

      The Switch "SWITCH_TO_LASTMODE":

      When this switch is defined, the command "TextMode(LastMode)" will be
      executed before the report output starts. The command switches back
      into the videomode, that was active at the start of the program. This
      can be very helpful when the main program switches to a graphics mode
      that isn't BIOS-supported or when textcolors are modified in a way,
      that the report in not readable. This switch does nothing under Windows.


      Example for turning switches off and on:
           active:   "{$DEFINE GERMAN_LANG}"
           inactive: "{not $DEFINE GERMAN_LANG}"


      HEAP DEBUGGING IN DETAIL _______________________________________________

      ___ Overlays ___________________________________________________________

      You can use the Heap Debugger also with programs, that uses overlay-
      technics. The Units USEHDEB and HDEB7? cannot be loaded as overlays.


      ___ DLLs _______________________________________________________________

      A DLL can be treated just like a normal self-running program. If a
      program, that is using the Heap Debugger, loads a DLL at runtime, then
      the Heap Debugger is not active for this DLL. On the other hand a DLL
      can use the Heap Debugger, without the heap operations in the main
      program being controlled. If the Heap Debugger is used for the DLL and
      the main program, then there will be two reports printed.

      To link the Heap Debugger to a DLL just insert the unit UseHDeb in the
      uses-clause of the librarys main file (with the title "Library").

      The exit-procedure of the unit UseHDeb (with the Reportoutput) will be
      done when the DLL ends. When is this? The DLL normally ends, when also
      the main program, that loaded the DLL, ends. But there are exceptions:
      If the main program is run with the external debugger, then the DLL will
      not end when the program is ended, but when the debugger is ended, what

      Page 13


      very often leads to a system crash. We suggest to use the command
      "FreeLibrary" to unload a DLL that uses the Heap Debugger. The report
      for the DLL will than be printed immediately. What was just described
      counts for DLLs under DOS and WINDOWS the same.

      Under Windows there is also another problem: The report output, that is
      done by the unit UseHDeb under Windows is printed into a WinCrt-window.
      That does not work with a DLL: The consequence of the try, to write into
      a WinCrt-window from within a DLL, is a runtime error or a complete
      missing of the output. Under DOS this problem will not occur.

      When using the Heap Debugger under Windows for a DLL, it is absolutely
      necessary to dump the report into a file. Herefor the switch
      "REPORT-TO-FILE" was prepared (see "Compilerswitches in USEHDEB").


      ___ Program Instances (Windows) ________________________________________

      When under windows a program, that links the Heap Debugger is started
      in several instances, the Heap Debugger will be installed only for the
      first instance. The following instances automatically use the already
      installed Heap Debugger. The output of the report will not be done until
      the ending of the last active instance of that program. The report then
      contains all wrong heap operations, that were done in all instances of
      that program.


      ___ Interrupts ________________________________________________________

      The Heap Debugger needs three free software interrupts. This means that
      when the Heap Debugger is installed it changes three free interrupt
      vectors and releases them at the end of the program. The Heap Debugger
      finds the free vectors itself within the range 78h to FFh. From this
      range you can exclude single vectors if you need some special vectors
      for own purposes. To do so you must change the parameter of the command
      "HeapDebInit([])". Change the empty set to set of vectors that you want
      be be left unchanged, e.g. "HeapDebInit([$F0..$FF]).


      ___ Stability and Performance __________________________________________

      As already explained the Heap Debugger should not be used as a part of a
      finished application. The Heap Debugger should only be used during the
      developing phase as a debugging tool.

      The permanent use of the Heap Debugger during the software development
      can help stabilize the developed software a lot and shorten the
      developmenting time.

      On the other hand the Heap Debugger can be a potential cause for
      program crashes, even if this has not been discovered yet. Following
      facts should be watched:

      - The Heap Debugger not only controls the correct usage of the heap
        memory. It also requires meap memory itself for this task. If a
        program occasionally has to allocate a large number of heap memory
        blocks, so the amount of needed extra memory for the Heap Debugger
        can be high. You should count with an extra 24 bytes for each
        allocated (and not yet deallocated) memory block.

      Page 14


      - The execution of the Heap Debugger requires extra space on the stack,
        as well as the execution of the memory operations and also the
        output of the report in the exit-procedure of the unit UseHDeb. Please
        notice that no stack-checks are done so that a lack of stack-space
        will cause a program crash.
      - When fatal errors in the application program are made in using the
        meap that can bring the program to a collapse. There might be
        constallations, in that the program doesn't crash when the Heap
        Debugger isn't linked. Nevertheless the causing error is dangerous.
        Such crashes can for instance happen, when the application tries to
        release a not allocated memory block.
      - The Heap Debugger needs for its work additional CPU-time. The more
        memory blocks are allocated, the more CPU-time the Heap Debugger
        requires, especially for releasing memory.
      - The Heap Debugger requires, as in the previous section mentioned, for
        its work three free software interrupts. The tree vectors are set to
        the addresses of three functions within the Heap Debugger and restored
        at the end of the program. When a program suddenly ends because of a
        fatal error and the exit procedure of the Unit UseHDeb insn't
        executed, then the interrupt vectors are not set to their old values.
        If such crashes happen very often, the Heap Debugger might not be able
        to find any free Interrupts and wont start.


      ___Intervention possibilities for the Programmer _______________________

      If you perhaps like to change the appearance of the Heap Debugger Report
      you can modify the sourcecode of the unit UseHDeb. Changes are only
      allowed for your own, non-commercial use.

      Beside the unit UseHDeb offers the following constants, which can be
      changed during at runtime:

      1)   SuspendHeapdeb : Boolean = false;

      If this constant is set to TRUE at runtime, then there will be no heap
      operations recorded by the Heap Debugger. After the reconversion of the
      value to FALSE the Heap Debugger will work normal. This can be
      useful to prevent quasi-static variables being listed in the report.

      2)   RecordZeroSize : Boolean = false;

      As long as this constant is FALSE, allocations and deallocations with
      the a length of zero be ignored by the Heap Debugger. Because such
      operations are just disfigurements and (as far as we know) cant make
      damage, this constant is preadjusted to FALSE.

      3)   RTEOnWrongSizedFree : Byte = 0;

      If in this constant is not zero, every deallocation, that doesn't have
      the same length as the fitting allocation (Flag "S"), will cause a
      runtime error immediately. The number of the runtime error is
      determined by this constant.

      4)   RTEOnUnknownFree : Byte = 0;

      If in this constant is not zero, every deallocation with not matching
      allocation (Flag "M"), will cause a runtime error immediately. The
      number of the runtime error is determined by this constant.

      Page 15


      KNOWN LIMITATIONS AND PROBLEMS _________________________________________

      ___ Mark/Release _______________________________________________________

      The Heap Debugger doesn't work with these commands. The usage of Release
      can cause the records of the Heap Debugger being destructed.

      However the commands Mark and Release are seldomly used, because
      they bring other problem with them in general. Probably they are still
      in the newest version of the compiler because of the compatibility. The
      usage of Mark and Release we generally do not advise. Mark and Release
      are only available under DOS.


      ___ MemAllocSeg ________________________________________________________

      The function MemAllocSeg in the unit Memory (under Windows: OMemory)
      is a big problem for the Heap Debugger: The job of this function
      is, to allocate a heap memory area, who's start address is exactly at
      the start of a memory segment (at the offset address 0000). To reach
      this, the function MemAllocSeg must use some tricks. We have to make
      differences between the target-platforms:

      Real Mode:

      To allocate a heap memory area with the offset address 0000, the
      function MemAllocSeg reserves with GetMem initially a little larger
      area, to afterwards immediately release with FreeMem a small part
      (8 Bytes), that is either located at the start or at the end of the
      just allocated area. Altho this is an offence against the rules, this
      trick isnt really illegal. The Heap Debugger "watches" these operations
      and will later list them in its report. This can for instance
      look like this:

         program TEST;
         uses UseHDeb, Memory;
         var p: pointer;
         begin
           {...}
           p := MemAllocSeg(100);
           FreeMem(p, 100);
         end.

      HEAP-DEBUGGER-DIAGNOSIS:
      1 pointers were registered
      3 debug-entries available
      list (Y/N) ? y

      No    Pointer   Size  Flags            Caller          File   Line
       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

      Or so:

      Page 16


      HEAP-DEBUGGER-DIAGNOSIS:
      1 pointers were registered
      3 debug-entries available
      list (Y/N) ? y

      No    Pointer   Size  Flags            Caller          File   Line
       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

      The programmer is more or less being forced, to accept such operations
      altho they appear risky.

      Protected Mode (DOS/DPMI):

      Here the function MemAllocSeg has it easier then in Real Mode:
      It just calls the function "MemAllocateBlock", which is made available
      by RTM.EXE that calls a corresponding DPMI-function. Through this
      a heap memory block is allocated, that starts at the offset address
      0000. As already explained in section "Global and Local Heap",
      the Heap Debugger notices nothing of this. The releasing of this
      heap memory block is normally done with the function FreeMem, about
      what the Heap Debugger takes notice. Our test program would show in
      the protected mode the following report:


      HEAP-DEBUGGER-DIAGNOSIS:
      0 pointers were registered
      1 debug-entries available
      list (Y/N) ? y

        No    Pointer   Size  Flags            Caller          File   Line
            059F:0000    100   F M    0001[0547]:003D      TEST.PAS      7

      Windows:

      Here we have the same situation as in the protected mode under DOS,
      except that the MemAllocSeg uses the function "GlobalAlloc" to allocate
      heap memory at the offset address 0000. Since this is a Global Heap-
      operation, the Heap Debugger will not notice anything. The releasing
      of this heap memory area with FreeMem will be registered. The
      consequence for the Heap Debugger is the same as in the protected mode.


      ___ BGI ________________________________________________________________

      During the initializing of BGI-Drivers the same phenomenon as described
      in the section "MemAllocSeg" might occur. Mostlikely the BGI-Drivers or
      the unit Graph have their own implementation of the function
      "MemAllocSeg".


      ___ TMemoryStream ______________________________________________________

      The method "ChangeListSize" of this stream-object uses MemAllocSeg,
      which was described above.

      Page 17


      ___ Heap Overrun _______________________________________________________

      The Heap Debugger, that is supposed to control the heap operations of a
      program, also needs heap memory for its work. In case the heap debugger
      cannot request anymore heap memory, because this is used up, then there
      will be an internal error number 203 reported. When the main program
      defines a heaperror-function, then this will be executed when a
      heap allocation in the Heap Debugger fails.


      ___ Program Break ______________________________________________________

      When a program, that uses the Heap Debugger, breaks execution without
      the exit-procedure of the unit UseHDeb is being run, then the by the
      Heap Debugger changed software interrupt vectors will not be restored.
      Non restored interrupt vectors, that are not used elsewhere, are of no
      danger. During a new Initialization of the Heap Debugger by a repeated
      run, there will be three other interrupt vectores searched. If the
      "hard" breaks repeat (approx. 40 times), there will sometime be no more
      free interrupt vectores and the Heap Debuggers initialization will
      fail. This then can only be fixed by a reboot of the computer.


      ___ WINCRT _____________________________________________________________

      If the main program is already using a WinCrt-Window and this is not
      closed with DoneWinCrt, before the exit-procedure of the Unit UseHDeb is
      run, then typically 2000 bytes of heap memory stay allocated, that then
      is listed in the Heap Debugger Report.

      Anyhow you should not be program a DoneWinCrt-command into the main
      program, because this brings up new problems.

      As already described in the section "DLLs", the Heap Debugger cannot
      dump into a WinCrt-window when a DLL is being used.

      In case of doubt you should try to take advantage of the possibility of
      the dumping the report into a file.
