The GNAT Debug Pool Facility (GNAT User’s Guide for Native Platforms)

#### 6.7.2 The GNAT Debug Pool Facility ¶

Using unchecked deallocation and unchecked conversion can easily lead to incorrect memory references. The problems generated by such references are usually difficult to find because the symptoms can be very remote from the origin of the problem. In such cases, it is very helpful to detect the problem as early as possible. This is the purpose of the Storage Pool provided by `GNAT.Debug_Pools`.

In order to use the GNAT specific debugging pool, you must associate a debug pool object with each of the access types that may be related to suspected memory problems. See Ada Reference Manual 13.11.

>     type Ptr is access Some_Type;
>     Pool : GNAT.Debug_Pools.Debug_Pool;
>     for Ptr'Storage_Pool use Pool;

`GNAT.Debug_Pools` is derived from a GNAT-specific kind of pool: the `Checked_Pool`. Such pools, like standard Ada storage pools, allow you to redefine allocation and deallocation strategies. They also provide a checkpoint for each dereference through the use of the primitive operation `Dereference` which is implicitly called at each dereference of an access value.

Once you have associated an access type with a debug pool, operations on values of the type may raise four distinct exceptions, which correspond to four potential kinds of memory corruption:

- `GNAT.Debug_Pools.Accessing_Not_Allocated_Storage`
- `GNAT.Debug_Pools.Accessing_Deallocated_Storage`
- `GNAT.Debug_Pools.Freeing_Not_Allocated_Storage`
- `GNAT.Debug_Pools.Freeing_Deallocated_Storage`

For types associated with a Debug_Pool, dynamic allocation is performed using the standard GNAT allocation routine. References to all allocated chunks of memory are kept in an internal dictionary. Several deallocation strategies are provided, allowing you to choose to release the memory to the system, keep it allocated for further invalid access checks, or fill it with an easily recognizable pattern for debug sessions. The memory pattern is the old IBM hexadecimal convention: `16#DEADBEEF#`.

See the documentation in the file `g-debpoo.ads` for more information on the various strategies.

Upon each dereference, a check is made that the access value denotes a properly allocated memory location. Here’s a complete example of use of `Debug_Pools`, which includes typical instances of memory corruption:

>     with GNAT.IO; use GNAT.IO;
>     with Ada.Unchecked_Deallocation;
>     with Ada.Unchecked_Conversion;
>     with GNAT.Debug_Pools;
>     with System.Storage_Elements;
>     with Ada.Exceptions; use Ada.Exceptions;
>     procedure Debug_Pool_Test is

>        type T is access Integer;
>        type U is access all T;

>        P : GNAT.Debug_Pools.Debug_Pool;
>        for T'Storage_Pool use P;

>        procedure Free is new Ada.Unchecked_Deallocation (Integer, T);
>        function UC is new Ada.Unchecked_Conversion (U, T);
>        A, B : aliased T;

>        procedure Info is new GNAT.Debug_Pools.Print_Info(Put_Line);

>     begin
>        Info (P);
>        A := new Integer;
>        B := new Integer;
>        B := A;
>        Info (P);
>        Free (A);
>        begin
>           Put_Line (Integer'Image(B.all));
>        exception
>           when E : others => Put_Line ("raised: " & Exception_Name (E));
>        end;
>        begin
>           Free (B);
>        exception
>           when E : others => Put_Line ("raised: " & Exception_Name (E));
>        end;
>        B := UC(A'Access);
>        begin
>           Put_Line (Integer'Image(B.all));
>        exception
>           when E : others => Put_Line ("raised: " & Exception_Name (E));
>        end;
>        begin
>           Free (B);
>        exception
>           when E : others => Put_Line ("raised: " & Exception_Name (E));
>        end;
>        Info (P);
>     end Debug_Pool_Test;

The debug pool mechanism provides the following precise diagnostics on the execution of this erroneous program:

>     Debug Pool info:
>       Total allocated bytes :  0
>       Total deallocated bytes :  0
>       Current Water Mark:  0
>       High Water Mark:  0

>     Debug Pool info:
>       Total allocated bytes :  8
>       Total deallocated bytes :  0
>       Current Water Mark:  8
>       High Water Mark:  8

>     raised: GNAT.DEBUG_POOLS.ACCESSING_DEALLOCATED_STORAGE
>     raised: GNAT.DEBUG_POOLS.FREEING_DEALLOCATED_STORAGE
>     raised: GNAT.DEBUG_POOLS.ACCESSING_NOT_ALLOCATED_STORAGE
>     raised: GNAT.DEBUG_POOLS.FREEING_NOT_ALLOCATED_STORAGE
>     Debug Pool info:
>       Total allocated bytes :  8
>       Total deallocated bytes :  4
>       Current Water Mark:  4
>       High Water Mark:  8