Previous: Switches for gnatmem, Up: The gnatmem Tool


21.3.3 Example of gnatmem Usage

The following example shows the use of gnatmem on a simple memory-leaking program. Suppose that we have the following Ada program:

     

with Unchecked_Deallocation; procedure Test_Gm is type T is array (1..1000) of Integer; type Ptr is access T; procedure Free is new Unchecked_Deallocation (T, Ptr); A : Ptr; procedure My_Alloc is begin A := new T; end My_Alloc; procedure My_DeAlloc is B : Ptr := A; begin Free (B); end My_DeAlloc; begin My_Alloc; for I in 1 .. 5 loop for J in I .. 5 loop My_Alloc; end loop; My_Dealloc; end loop; end;

The program needs to be compiled with debugging option and linked with gmem library:

     $ gnatmake -g test_gm -largs -lgmem

Then we execute the program as usual:

     $ test_gm

Then gnatmem is invoked simply with

     $ gnatmem test_gm

which produces the following output (result may vary on different platforms):

     Global information
     ------------------
        Total number of allocations        :  18
        Total number of deallocations      :   5
        Final Water Mark (non freed mem)   :  53.00 Kilobytes
        High Water Mark                    :  56.90 Kilobytes
     
     Allocation Root # 1
     -------------------
      Number of non freed allocations    :  11
      Final Water Mark (non freed mem)   :  42.97 Kilobytes
      High Water Mark                    :  46.88 Kilobytes
      Backtrace                          :
        test_gm.adb:11 test_gm.my_alloc
     
     Allocation Root # 2
     -------------------
      Number of non freed allocations    :   1
      Final Water Mark (non freed mem)   :  10.02 Kilobytes
      High Water Mark                    :  10.02 Kilobytes
      Backtrace                          :
        s-secsta.adb:81 system.secondary_stack.ss_init
     
     Allocation Root # 3
     -------------------
      Number of non freed allocations    :   1
      Final Water Mark (non freed mem)   :  12 Bytes
      High Water Mark                    :  12 Bytes
      Backtrace                          :
        s-secsta.adb:181 system.secondary_stack.ss_init

Note that the GNAT run time contains itself a certain number of allocations that have no corresponding deallocation, as shown here for root #2 and root #3. This is a normal behavior when the number of non-freed allocations is one, it allocates dynamic data structures that the run time needs for the complete lifetime of the program. Note also that there is only one allocation root in the user program with a single line back trace: test_gm.adb:11 test_gm.my_alloc, whereas a careful analysis of the program shows that 'My_Alloc' is called at 2 different points in the source (line 21 and line 24). If those two allocation roots need to be distinguished, the backtrace depth parameter can be used:

     $ gnatmem 3 test_gm

which will give the following output:

     Global information
     ------------------
        Total number of allocations        :  18
        Total number of deallocations      :   5
        Final Water Mark (non freed mem)   :  53.00 Kilobytes
        High Water Mark                    :  56.90 Kilobytes
     
     Allocation Root # 1
     -------------------
      Number of non freed allocations    :  10
      Final Water Mark (non freed mem)   :  39.06 Kilobytes
      High Water Mark                    :  42.97 Kilobytes
      Backtrace                          :
        test_gm.adb:11 test_gm.my_alloc
        test_gm.adb:24 test_gm
        b_test_gm.c:52 main
     
     Allocation Root # 2
     -------------------
      Number of non freed allocations    :   1
      Final Water Mark (non freed mem)   :  10.02 Kilobytes
      High Water Mark                    :  10.02 Kilobytes
      Backtrace                          :
        s-secsta.adb:81  system.secondary_stack.ss_init
        s-secsta.adb:283 <system__secondary_stack___elabb>
        b_test_gm.c:33   adainit
     
     Allocation Root # 3
     -------------------
      Number of non freed allocations    :   1
      Final Water Mark (non freed mem)   :   3.91 Kilobytes
      High Water Mark                    :   3.91 Kilobytes
      Backtrace                          :
        test_gm.adb:11 test_gm.my_alloc
        test_gm.adb:21 test_gm
        b_test_gm.c:52 main
     
     Allocation Root # 4
     -------------------
      Number of non freed allocations    :   1
      Final Water Mark (non freed mem)   :  12 Bytes
      High Water Mark                    :  12 Bytes
      Backtrace                          :
        s-secsta.adb:181 system.secondary_stack.ss_init
        s-secsta.adb:283 <system__secondary_stack___elabb>
        b_test_gm.c:33   adainit

The allocation root #1 of the first example has been split in 2 roots #1 and #3 thanks to the more precise associated backtrace.