comp.lang.ada
 help / color / mirror / Atom feed
From: "Hervé Bitteur" <Herve.Bitteur@France.Sun.COM>
Subject: Got bitten by GNAT.Table
Date: Mon, 05 Mar 2001 02:56:26 +0100
Date: 2001-03-05T01:55:47+00:00	[thread overview]
Message-ID: <3AA2F24A.3843E70@France.Sun.COM> (raw)
In-Reply-To: 3AA2C4C4.CF3E6457@blops.mydiax.ch

GNAT.Table is useful to provide dynamically growing arrays.
However I recently discovered the reason why I occasionally 
had other data overwritten, if not access violation errors.
Here is a simple test program that you can run from the command line,
with just one argument: the upper bound of the loop.

-------------------------------------------------------------------------
with GNAT.Table;
with Ada.Command_Line;
procedure Test_Table
is
   Init : constant Natural := Natural'Value (Ada.Command_Line.Argument
(1));
   package Pkg is new GNAT.Table
     (Table_Component_Type => Character,
      Table_Index_Type     => Natural,
      Table_Low_Bound      => 1,
      Table_Initial        => Init,
      Table_Increment      => 100);
begin
   for I in 1 .. Init + 1 loop          -- To force one reallocation
      Pkg.Table (Pkg.Allocate) := 'a';  -- <<<<<
   end loop;
end Test_Table;
-------------------------------------------------------------------------

On my Windows 98 environment, using GNAT 3.13p, 
I'm getting the following results :

$> test_table 523200
(or less than 523200) is OK, but

$> test_table 523201
(or higher) leads to:
raised PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION

Using Integers (4 bytes) instead of Characters (1 byte) also crashes,
the limit is slightly higher (I would have expected a lower limit).

Anyway, if I modify the little program (line marked with -- <<<<<)
so that instead of
      Pkg.Table (Pkg.Allocate) := 'a';
I use
      declare
         Last : Natural := Pkg.Allocate;
      begin
         Pkg.Table (Last) := 'a';
      end;
The program then runs OK. For example test_table 100_000_000 is fine
(1_000_000_000 however raises storage_error, but I can understand this)

How could we explain the result?
If the call to GNAT.Table.Allocate results in an actual reallocation
of the buffer, then at this precise moment, we modify the very value
of Table which is in fact an array reference.
- Allocate increases the current Last value and returns the previous
last value +1
- Table (xxx) is the combination of dereferencement + indexation.
The problem is that when we've reached the end of the allocated array,
the Allocate function reallocates the array, thus changing the array
reference ON-THE-FLY.

I should dig into the generated code but I suspect that the construction 
"Table (Allocate)" is not kept coherent when the array is reallocated, 
so the need to explicitly separate the two operations.

To prevent this, I would suggest to replace the Allocate function, by
a simple procedure. Any one can still retrieve the current last value,
by calling the Table.Last function.

Bye,
-- Herv�

-- 
      /\             Herv� BITTEUR                            
     \\ \            EMEA IT Architect
    \ \\ /           SUN MICROSYSTEMS FRANCE                  
   / \/ / /          13, avenue Morane Saulnier
  / /   \//\         78142 V�lizy cedex France
  \//\   / /         
   / / /\ /          Email  : Herve.Bitteur@France.Sun.COM
    / \\ \           Office : +33 (0)1.30.67.51.12
     \ \\            
      \/             Fax.   : +33 (0)1.30.67.53.06



  parent reply	other threads:[~2001-03-05  1:56 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-03-02 13:12 GNAT Ada 3.13 + DOS revisted Ashley Collins
2001-03-02 14:34 ` Cesar Rabak
2001-03-02 20:16 ` Randy Brukardt
2001-03-02 21:06   ` Ted Dennison
2001-03-03  1:28     ` Randy Brukardt
2001-03-03  3:28     ` Al Christians
2001-03-03  9:17       ` Gautier de Montmollin
2001-03-03 16:23         ` tmoran
2001-03-04 22:42           ` Gautier de Montmollin
2001-03-04 23:36             ` tmoran
2001-03-05  1:45               ` Al Christians
2001-03-05  3:01                 ` tmoran
2001-03-05  1:56             ` Hervé Bitteur [this message]
2001-03-05 12:41               ` Got bitten by GNAT.Table Mario Amado Alves
2001-03-07 21:33               ` Stephen Leake
2001-03-08  4:07                 ` Hervé Bitteur
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox