comp.lang.ada
 help / color / mirror / Atom feed
From: Per Sandberg <per.sandberg@sandat.dyndns.org>
Subject: Re: GNAT Allocation of a very large record
Date: Wed, 14 Aug 2013 21:32:10 +0200
Date: 2013-08-14T21:32:10+02:00	[thread overview]
Message-ID: <20130814213210.5ebf41e7@lufsen.sandat.dyndns.org> (raw)
In-Reply-To: 9de9c3bf-c4c5-466f-a8cd-fca992daecbe@googlegroups.com

Tried 4 different GCC:s and one failed:
gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) x86 ok
gcc 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC) x86_64 ok
gcc 4.7.3 20130318 for GNAT Pro 7.2.0w (20130317) (GCC) x86_64 ok
gcc 4.4.5 (Debian 4.4.5-8) arm (raspberry-pi) fail

It seems as there is a bug in your particular instance of GCC as well
as the GCC for the pi.


/Per




On Tue, 13 Aug 2013 20:50:21 -0700 (PDT)
hyunghwan.chung@gmail.com wrote:

> Hi, 
> 
> The program at the bottom of this message, when compiled with GNAT
> 4.6 on Ubuntu12/x86_64, seems to corrupt memory, ending up with a
> malloc error message.
> 
> $ ./x1
> 1. Kind: POINTER_OBJECT Size:  10
> x1: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr)
> (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct
> malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size)
> >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk,
> >fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 *
> >(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned
> >long)old_end & pagemask) == 0)' failed. ^C
> 
> On some other platforms (i.e. debian/armv5tel, gcc/gnat 4.4.5), just
> segmentation fault.
> 
> I expect an output like this, meaning that the second call to 'new'
> should raise an exception like storage_error.
> 
> $ ./x1
> 1. Kind: POINTER_OBJECT Size:  10
> 2. Allocation Failed
> 
> You'd get the result like above if you changed the upper bound of the
> range of Pointer_Obje



ct_Size from Storage_Count'Last to
> (OBJECT_DATA_BYTES / (Object_Pointer'Max_Size_In_Storage_Elements *
> System.Storage_Unit)).
> 
> The new upper bound has been defined so that
> Pointer_Object_Record'Size don't exceed 2 ** 63 - 1 (System.Max_Int).
> On an 32-bit platform, the upper bound seems to be able to reach
> OBJECT_DATA_BYTES / Object_Pointer'Max_Size_In_Storage_Elements. With
> this upper bound on the 32-bit platform, Pointer_Object_Record'Size
> may go beyond 2 ^ 31 - 1 but
> Pointer_Object_Record'Max_Size_In_Storage_Elements falls below 2 ^ 31
> - 1. 
> 
> Anyway, when the upper bound is set to Storage_Count'Last,
> Pointer_Object_Record'Max_Size_In_Storage_Elements and
> Pointer_Object_Record'Size seem to wrap around to an undesired value
> 
> The problem is that neither Constraint_Error nor Storage_Error is
> raised when the size of a record is very large. I'd like to have a
> graceful way to catch a ridiculously large size given to the function
> and handle the exception properly without ending up with segmentation
> fault or something similar.
> 
> Is it a bug of the GNU Ada compiler or am i doing anything wrong?
> 
> Thanks,
> Hyung-Hwan
> 
> ------------------------------------------------------------------------------- 
> with Ada.Text_IO; 
> with System;
> with Ada.Unchecked_Conversion;
> 
> procedure X1 is
> 
> 	type Storage_Element is mod 2 ** System.Storage_Unit;
> 	for Storage_Element'Size use System.Storage_Unit;
> 	type Storage_Offset is range -(2 ** (System.Word_Size -
> 1)) ..  +(2 ** (System.Word_Size - 1)) - 1; subtype Storage_Count is
> Storage_Offset range 0 .. Storage_Offset'Last;
> 
> 	subtype Object_Byte      is Storage_Element;
> 	subtype Object_Character is Wide_Character;
> 	subtype Object_String    is Wide_String;
> 
> 	type Object_Kind is (Pointer_Object, Character_Object,
> Byte_Object); for Object_Kind use (Pointer_Object => 0,
> Character_Object => 1, Byte_Object => 2);
> 
> 	type Object_Record;
> 	type Object_Pointer is access all Object_Record;
> 
> 	type Byte_Array is array (Storage_Count range <>) of
> Object_Byte; type Character_Array is array (Storage_Count range <>)
> of Object_Character; type Pointer_Array is array (Storage_Count range
> <>) of Object_Pointer;
> 
> 	type Object_Record (Kind: Object_Kind; Size: Storage_Count)
> is record Flags: Standard.Integer range 0 .. 3;-- := 0;
> 		Extra: Standard.Integer range 0 .. 1;-- := 0;
> 		Unit:  Standard.Integer range 0 .. 4;-- := 0;
> 		Class: Object_Pointer;-- := null;
> 
> 		case Kind is
> 			when Pointer_Object =>
> 				Pointer_Slot: Pointer_Array (1 ..
> Size);-- := (Others => null); when Character_Object =>
> 				Character_Slot: Character_Array (0 ..
> Size);-- := (Others => Object_Character'Val(0)); when Byte_Object =>
> 				Byte_Slot: Byte_Array (1 ..
> Size);-- := (Others => 0); end case;
> 	end record;
> 	for Object_Record use record
> 		Kind  at 0 range 0 .. 7;
> 		Flags at 1 range 0 .. 2;
> 		Extra at 1 range 3 .. 3;
> 		Unit  at 1 range 4 .. 7;
> 	end record;
> 
> 	subtype Empty_Object_Record is Object_Record (Byte_Object, 0);
> 	-- the number of bytes in an object header. this is fixed in
> size OBJECT_HEADER_BYTES: constant Storage_Count :=
> Empty_Object_Record'Max_Size_In_Storage_Elements; -- the largest
> number of bytes that an object can hold after the header
> OBJECT_DATA_BYTES: constant Storage_Count := Storage_Count'Last -
> OBJECT_HEADER_BYTES;
> 
> 	subtype Pointer_Object_Size is Storage_Count range
> 		Storage_Count'First .. (OBJECT_DATA_BYTES /
> (Object_Pointer'Max_Size_In_Storage_Elements * System.Storage_Unit));
> --	Storage_Count'First .. Storage_Count'Last;
> 
> 	procedure Alloc_Pointer_Object (Size: in Pointer_Object_Size;
> Result: out Object_Pointer) is subtype Pointer_Object_Record is
> Object_Record (Pointer_Object, Size); type Pointer_Object_Pointer is
> access Pointer_Object_Record; function To_Object_Pointer is new
> Ada.Unchecked_Conversion (Pointer_Object_Pointer, Object_Pointer);
> Ptr: Pointer_Object_Pointer; begin
>    		--Ada.Text_IO.Put_Line
> (Pointer_Object_Record'Size'Img); --Ada.Text_IO.Put_Line
> (Pointer_Object_Record'Max_Size_In_Storage_Elements'Img); Ptr := new
> Pointer_Object_Record'( Kind => Pointer_Object, 
> 			Size => Size,
> 			Flags => 0,
> 			Extra => 0,
> 			Unit => 0,
> 			Class => null,
> 			Pointer_Slot => (others=>null)
> 		);
> 
> 		Result := To_Object_Pointer (Ptr);
> 	exception
> 		when others =>
> 			Result := null;
> 	end Alloc_Pointer_Object;
> 
> 
> 	ObjPtr: Object_Pointer;
> begin
> 
> 	Alloc_Pointer_Object (10, ObjPtr);
> 	if ObjPtr = null then
> 		Ada.Text_IO.Put_Line ("1. Allocation Failed");
> 	else
> 		Ada.Text_IO.Put_Line ("1. Kind: " &
> Object_Kind'Image(ObjPtr.Kind)  & " Size: " &
> Storage_Count'Image(ObjPtr.Size)); end if;
> 
> 	Alloc_Pointer_Object (Pointer_Object_Size'Last, ObjPtr);
> 	if ObjPtr = null then
> 		Ada.Text_IO.Put_Line ("2. Allocation Failed");
> 	else
> 		Ada.Text_IO.Put_Line ("2. Kind: " &
> Object_Kind'Image(ObjPtr.Kind)  & " Size: " &
> Storage_Count'Image(ObjPtr.Size)); end if;
> 
> end X1;


  reply	other threads:[~2013-08-14 19:32 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-14  3:50 GNAT Allocation of a very large record hyunghwan.chung
2013-08-14 19:32 ` Per Sandberg [this message]
2013-08-14 20:08   ` Anh Vo
2013-08-15  1:06     ` Hyung-Hwan Chung
2013-08-15  8:59 ` Georg Bauhaus
2013-08-15 14:27 ` Robert A Duff
2013-08-16  1:18   ` Hyung-Hwan Chung
replies disabled

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