[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmem
gnatmem
, is a tool that monitors dynamic allocation and
deallocation activity in a program, and displays information about
incorrect deallocations and possible sources of memory leaks. Gnatmem
provides three type of information:
15.1 Running gnatmem
15.2 Switches for gnatmem
15.3 Example of gnatmem
Usage15.4 Implementation note
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmem
The gnatmem
command has the form
$ gnatmem [n] [-o file] user_program [program_arg]* or $ gnatmem [n] -i file |
Gnatmem must be supplied with the executable to examine, followed by its run-time inputs. For example, if a program is executed with the command:
$ my_program arg1 arg2 |
gnatmem
control using the command:
$ gnatmem my_program arg1 arg2 |
The program is transparently executed under the control of the debugger
20.1 The GNAT Debugger GDB. This does not affect the behavior
of the program, except for sensitive real-time programs. When the program
has completed execution, gnatmem
outputs a report containing general
allocation/deallocation information and potential memory leak.
For better results, the user program should be compiled with
debugging options 3.2 Switches for gnatgcc
.
Here is a simple example of use:
*************** debut cc
$ gnatmem test_gm Global information ------------------ Total number of allocations : 45 Total number of deallocations : 6 Final Water Mark (non freed mem) : 11.29 Kilobytes High Water Mark : 11.40 Kilobytes . . . Allocation Root # 2 ------------------- Number of non freed allocations : 11 Final Water Mark (non freed mem) : 1.16 Kilobytes High Water Mark : 1.27 Kilobytes Backtrace : test_gm.adb:23 test_gm.alloc . . . |
The first block of output give general information. In this case, the Ada construct "new" was executed 45 times, and only 6 calls to an unchecked deallocation routine occurred.
Subsequent paragraphs display information on all allocation roots. An allocation root is a specific point in the execution of the program that generates some dynamic allocation, such as a "new" construct. This root is represented by an execution backtrace (or subprogram call stack). By default the backtrace depth for allocations roots is 1, so that a root corresponds exactly to a source location. The backtrace can be made deeper, to make the root more specific.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmem
gnatmem
recognizes the following switches:
-q
n
-o file
-i file
gnatmem
processing starting from file
which has been generated
by a previous call to gnatmem
with the -o switch. This is useful for
post mortem processing.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmem
Usage
The first example shows the use of gnatmem
on a simple 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:
$ gnatmake -g test_gm |
gnatmem
is invoked simply with
$ gnatmem test_gm |
which produces 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 : 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 #1. This is a normal behavior when the number of non freed allocations is one, it locates 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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmem
executes the user program under the control of gnatgdb
using
a script that sets breakpoints and gathers information on each dynamic
allocation and deallocation. The output of the script is then analyzed
by gnatmem
in order to locate memory leaks and their origin in the
program. Gnatmem works by recording each address returned by the
allocation procedure (__gnat_malloc
)
along with the backtrace at the
allocation point. On each deallocation, the deallocated address is
matched with the corresponding allocation. At the end of the processing,
the unmatched allocations are considered potential leaks. All the
allocations associated with the same backtrace are grouped together and
form an allocation root. The allocation roots are then sorted so that
those with the biggest number of unmatched allocation are printed
first. A delicate aspect of this technique is to distinguish between the
data produced by the user program and the data produced by the gnatgdb
script. Currently, on systems that allow probing the terminal, the gnatgdb
command "tty" is used to force the program output to be redirected to the
current terminal while the gnatgdb output is directed to a file or to a
pipe in order to be processed subsequently by gnatmem
.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |