comp.lang.ada
 help / color / mirror / Atom feed
From: M E Leypold <development-2006-8ecbb5cc8aREMOVETHIS@ANDTHATm-e-leypold.de>
Subject: Compiler Bug or what I'm doing wrong?
Date: 20 Jun 2006 18:56:06 +0200
Date: 2006-06-20T18:56:06+02:00	[thread overview]
Message-ID: <05lkrrojfd.fsf@hod.lan.m-e-leypold.de> (raw)



Hi all,

the following happens with GNAT 3.15p on Debian. My impression is,
that finalization during reading with the compiler generated
'Read-Attribute is not handled right in variant records, but I might
be wrong. Let me first expose the problem and my sample code.

I have the following Program (explanations below):


    with Sf.Cases;
    use  Sf.Cases;

    with Sf.Fieldtypes;
    use  Sf.Fieldtypes;

    with Ada.Streams.Stream_IO;
    use  Ada.Streams.Stream_IO;


    procedure Demo.Bug3 is

       procedure Write_Record
       is
         R : Fall_Datensatz;

         F : File_Type;
         S : Stream_Access;
       begin
          Create( F , Name => "tmp-bug3" );
          S := Stream(F);
          Set_Zugang(R, SelbstMelderIn);          -- [**]
          -- Fall_Datensatz'Output(S,R); -- [2a]
          Fall_Datensatz'Write(S,R);     -- [1a]
          Close(F);
       end;

       Function Get_Record return Fall_Datensatz
       is
          R: Fall_Datensatz;
          F : File_Type;
          S : Stream_Access;
       begin
          Open( F , Mode => In_File, Name => "tmp-bug3" );
          S := Stream(F);

          -- R := Fall_Datensatz'Input(S); -- [2b]
          Fall_Datensatz'Read(S,R);        -- [1b]
          Close( F );
          return R;
       end;

       R : Fall_Datensatz;

    begin
       Write_Record;
       R := Get_Record;
    end;


It instantiated a record with default initialization, changes a
discriminant in a which controls a variant part in the record (at [**]
Set_Zugang will be explained later), and then stores the record in a
file. When rereading the file (Get_Record), I get the following
exception:


   "raised PROGRAM_ERROR : demo-bug3.adb:38 finalize raised exception"

Running it under debugger control I get 

   (gdb) exec-file demo-bug3
   (gdb) run
   Starting program: /home/mel/cvswork/statfix/src2/demo-bug3

   Program received signal SIGSEGV, Segmentation fault.
   0x4098d354 in mallopt () from /lib/libc.so.6
   (gdb)

   (gdb) bt 5
   #0  0x4098d354 in mallopt () from /lib/libc.so.6
   #1  0x4098c15f in free () from /lib/libc.so.6
   #2  0x408f4e84 in __gnat_free () from /usr/lib/libgnat-3.15p.so.1
   #3  0x4082ac79 in ada__strings__unbounded__finalize__2 ()
      from /usr/lib/libgnat-3.15p.so.1
   #4  0x080c9fe5 in <demo__bug3__get_record___read654___read1116___read1147> (
       s=0x80e2e00, v=@0xbfffc39c, <sF>=0) at demo-bug3.adb:38
   (More stack frames follow...)
   (gdb)

which makes me suspect that a finalizer is run on non-appropriate data
(i.e. on the wrong part of a variant). I'll attach more stack traces
below, but first let me explain the data structure Fall_Datensatz
(which is defined in SF.Cases). I'm showing only the parts that are
actually touched by the program:


   type PA_Kontakt_Ergebnis ( Erfolg : Di_State := Keine_Angabe ) is record

      case Erfolg is
         when Ja     => Kontakt_Ergebnis : Auswahl_Kontakt_Ergebnis := Keine_Angabe;         
         when others => null;
      end case;
   end record;


   type PA_Kontakt_Verlauf
     ( Kontakt_Methode : Auswahl_Kontakt_Methode := Keine_Angabe )
   is record
      case Kontakt_Methode is
         when Keine_Angabe => null;
         when Keinen       => null;
         when Others       => Ergebnis : PA_Kontakt_Ergebnis;
      end case;
   end record;


   type Zugangs_Daten( KlientIn_Zugang : Auswahl_KlientIn_Zugang := Keine_Angabe ) is record

      case KlientIn_Zugang is

         when  Proaktiver_Kontakt  =>

            Kontakt_Vermittlung : Angabe_Kontakt_Vermittlung ;
            PA_Kontakt          : PA_Kontakt_Verlauf         ;

         when      SelbstmelderIn  =>

            KlientIn_Aufmerksamkeit : Angabe_Klientin_Aufmerksamkeit;

         when              others  =>  null;
      end case;
   end record;




   type Fall_Datensatz
     ( KJB_Verf�gbar : Boolean := True ; Notizen_Verf�gbar : Boolean := True )
   is record

      Aktenzeichen  : Fall_Aktenzeichen;
      Tat           : Fall_Merkmale     (Notizen_Verf�gbar);

      Opfer         : Personen_Merkmale (Notizen_Verf�gbar);
      T�ter         : Personen_Merkmale (Notizen_Verf�gbar);

      Zugang        : Zugangs_Daten;
      Polizei       : Angaben_Polizei_Einsatz;

      Beratung      : Beratungsverlauf  (Notizen_Verf�gbar);

      Kinder        : Kinder_Daten; -- (KJB_Verf�gbar, Notizen_Verf�gbar);

      case KJB_Verf�gbar is
         when  True   => null; -- KJB : ...
         when  False  => null;
      end case;
   end record;


The Unbounded Strings are hidden in Angabe_Kontakt_Vermittlung and
Angabe_Klientin_Aufmerksamkeit which are actually Types defined via a
generic package as an enumeration type with an optional comment (only
to be given in some cases):


   type Data is record
      Choice  : Choice_Type      := Choice_Type'First;
      Comment : Unbounded_String := Null_Unbounded_String;
   end record;


(I'll give the complete interface below, but this post becomes pretty
longish, so I'll restrict myself to what I consider the relevant parts).

The procedure Set_Zugang modifies the diosriminant of Zugangs_Daten in
the following way:


   procedure Set_Zugang ( D :  in out Zugangs_Daten ; Z : Auswahl_KlientIn_Zugang )
   is begin

      if Z /= D.KlientIn_Zugang then

         case Z is

            when Selbstmelderin      =>
               declare New_D : Zugangs_Daten(Selbstmelderin);
               begin
                  D := New_D ;
               end;

            when Proaktiver_Kontakt  =>
               declare New_D : Zugangs_Daten(Proaktiver_Kontakt);
               begin   D := New_D ; end;

            when Keine_Angabe        => D := (KlientIn_Zugang => Keine_Angabe ) ;
         end case;
      end if;
   end;


   procedure Set_Zugang ( DS :  in out Fall_Datensatz ; Z : Auswahl_KlientIn_Zugang) is begin

      Set_Zugang( DS.Zugang, Z );
   end;

(The idea is to have the initialisation defaults if and only if the
discrimant is changed).

If  (in gdb) I step up some stackframes and print the record R in
Get_Record I get the following


  (...)  zugang => (klientin_zugang => selbstmelderin,
         klientin_aufmerksamkeit => ( choice => keine_angabe, comment
         => (prev => 0x0, next => 0x0, reference => Cannot access
         memory at address 0x7a9f08

This is also what led me to the impression that first the discriminant
is overwritten and the the finalizer(s) for the new variant part
("when SelbstMelderIn") are run (on random bit patterns) instead of
the finalizers for the default variant part ("when Keine_Angabe
..."). 

(Actually I'd have expected in the case of discriminant records that
the whole thingy works like this: Run all finalizers in variant parts
if any, only then read the discriminant, run the initializers in the
new variant parts, then read the rest of the record).

After having a look into Barnes "Programming in Ada 95" again, I
thought, that perhaps I should use 'Input and 'Output instead of 'Read
an 'Write. This fixed the problem in the case above (options [2a] and
[2b]), but unfortunately failed to fix the the problem in the larger
program from which these fragments come.

Of course the bug is a Heisenbug so small changes in Fall_Datensatz or
the order of code execuation in the larger program make it disappear
which made it difficult in the first place to construct a relatively
small example w/o GUI which succeeds in reproducing the bug. 

Therefore I think (but again I'm not sure) that the fact that the bug
goes away with 'Input and Output instead of 'Read/'Write is just part
of it's elusive character not evidence of a fix. Also, since records
with default discriminants are definite I think 'Read and 'Write
should be OK for IO. Am I not right?

I've googled a bit, but didn't find anything on that, eehm,
"effect". But maybe I didn't use the right keywords. 

Is this a known bug with GNAT 3.15p or am I doing anything wrong?

Your help/input (also suggestions for workaround or confirmation that
this indeed a GNAT bug) would be greatly appreciated.

(Ludovico: I'll file an entry into Debian bug tracking soon. Just
looking for confirmation here first).

Regards -- Markus



ATTACHEMENTS: Backtraces and more code
--------------------------------------

  Sf.Single-Choices (Unit interface from which the types Angabe_* are instantiated) 
  ------------------
  
     with Ada.Strings.Unbounded;
     use  Ada.Strings.Unbounded;

     generic

        type Choice_Type   is (<>);
        type Choice_List   is array (Integer range <>) of Choice_Type;

        Allow_Comment_List : Choice_List;

     package Sf.Single_Choice is

        type Data is private;

        procedure Set( D : in out Data ; C : Choice_Type );
        function  Get( D : Data ) return Choice_Type;
        function  ID ( D : Data ) return Integer;

        function  Get_Comment( D : Data ) return String;
        procedure Set_Comment( D : in out Data; S : String );

        procedure Set_From_Integer( D : in out Data ; I : Integer );

        procedure Set( D : in out Data ; I : Integer ) renames Set_From_Integer;

        procedure Reset ( D : in out Data );

     private

        type Flags is array (Choice_Type) of Boolean;

        function Get_Comment_Allowed_Vector return Flags;

        Comment_Allowed : constant Flags := Get_Comment_Allowed_Vector;

        type Data is record
           Choice  : Choice_Type      := Choice_Type'First;
           Comment : Unbounded_String := Null_Unbounded_String;
        end record;
     end;



  complete backtrace
  ------------------

  #0  0x4098d354 in mallopt () from /lib/libc.so.6
  #1  0x4098c15f in free () from /lib/libc.so.6
  #2  0x408f4e84 in __gnat_free () from /usr/lib/libgnat-3.15p.so.1
  #3  0x4082ac79 in ada__strings__unbounded__finalize__2 ()
     from /usr/lib/libgnat-3.15p.so.1
  #4  0x080c9fe5 in <demo__bug3__get_record___read654___read1116___read1147> (
      s=0x80e2e00, v=@0xbfffc39c, <sF>=0) at demo-bug3.adb:38
  #5  0x080ca136 in <demo__bug3__get_record___read654___read1116> (s=0x80e2e00,
      v=@0xbfffc384, <sF>=0, <vF>=false) at demo-bug3.adb:38
  #6  0x080d5997 in <demo__bug3__get_record___read654> (s=0x80e2e00, v=@0xbfffc108,
      <sF>=0, <vF>=false) at demo-bug3.adb:38
  #7  0x080d869f in demo.bug3.get_record () at demo-bug3.adb:38
  #8  0x080dd625 in demo.bug3 () at demo-bug3.adb:48
  #9  0x080640dd in main (argc=1, argv=(system.address) 0xbffff8a4,
      envp=(system.address) 0xbffff8ac) at b~demo-bug3.adb:244
  #10 0x40930e36 in __libc_start_main () from /lib/libc.so.6


  more information
  ----------------

  I've generated a core and also can reproduce the SIGSEGV in this
  configuration 100% of the time. Don't hesitate to ask for more
  debugger output or more code.





             reply	other threads:[~2006-06-20 16:56 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-06-20 16:56 M E Leypold [this message]
2006-06-21  7:44 ` Compiler Bug or what I'm doing wrong? Ludovic Brenta
2006-06-21 12:29   ` M E Leypold
2006-06-21 12:46     ` Alex R. Mosteo
2006-06-21 13:23       ` M E Leypold
2006-06-22 19:10         ` Simon Wright
2006-06-23  8:24         ` Ludovic Brenta
2006-06-23 13:14         ` Alex R. Mosteo
2006-06-23 13:24           ` Alex R. Mosteo
2006-06-24 20:33             ` Simon Wright
2006-06-24 20:56               ` M E Leypold
2006-06-26  7:32                 ` Ludovic Brenta
2006-06-26 11:16                   ` M E Leypold
2006-06-26 12:13                     ` [Ada in Debian] GtkAda and GNAT versions Ludovic Brenta
2006-06-26 12:25                       ` M E Leypold
2006-06-27 20:55                   ` Compiler Bug or what I'm doing wrong? Simon Wright
2006-06-27 22:26                     ` Ludovic Brenta
2006-06-22  2:07       ` James Dennett
2006-06-22  6:37         ` Duncan Sands
2006-06-22 16:53           ` M E Leypold
2006-06-22 19:01             ` Pascal Obry
2006-06-23  8:37               ` M E Leypold
2006-06-22 19:05             ` Dmitry A. Kazakov
2006-06-23  4:47               ` Jeffrey R. Carter
2006-06-23 12:26               ` Stephen Leake
2006-06-23 13:11                 ` Dmitry A. Kazakov
2006-06-23 13:15                 ` Alex R. Mosteo
2006-06-23  9:55 ` A smaller self contained test case. Was: " M E Leypold
2006-06-23 10:03   ` M E Leypold
2006-06-23 11:04   ` And a Workaround: Was: A smaller test case / Compiler Bug M E Leypold
2006-06-23 11:12     ` Possible memory leaks when reading/writing variant records M E Leypold
2006-06-24 11:46   ` A smaller self contained test case. Was: Compiler Bug or what I'm doing wrong? Dmitry A. Kazakov
2006-06-24 12:27     ` M E Leypold
2006-06-24 12:52       ` Dmitry A. Kazakov
2006-06-24 13:53         ` M E Leypold
2006-06-24 19:58           ` Dmitry A. Kazakov
2006-06-24 20:22             ` M E Leypold
2006-06-25  7:59               ` Dmitry A. Kazakov
2006-06-25 10:51                 ` M E Leypold
2006-06-26  6:22                   ` Martin Dowie
2006-06-24 21:21             ` M E Leypold
2006-06-25 21:36   ` M E Leypold
2006-06-26 21:53   ` Possibly fixed in gcc 4.1.1, but bug box -- Was: Re: A smaller self contained test case M E Leypold
2006-06-27 18:24     ` Alex R. Mosteo
2006-06-27 22:58       ` M E Leypold
2006-06-28 10:32         ` Alex R. Mosteo
2006-07-03  1:38         ` Steve Whalen
2006-07-03 10:36           ` M E Leypold
2006-06-28  8:41       ` Ludovic Brenta
2006-06-28  8:51         ` Georg Bauhaus
2006-06-28 10:43         ` Alex R. Mosteo
2006-06-23 10:00 ` Compiler Bug or what I'm doing wrong? M E Leypold
  -- strict thread matches above, loose matches on Subject: below --
2006-06-23 17:42 Anh Vo
2006-06-26  6:59 ` Alex R. Mosteo
replies disabled

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