| -- { dg-do run } |
| -- { dg-options "-gnatws" } |
| |
| with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; |
| with Ada.Text_IO; use Ada.Text_IO; |
| with System.Parameters; use System.Parameters; |
| with System.Secondary_Stack; use System.Secondary_Stack; |
| |
| procedure Sec_Stack2 is |
| procedure Overflow_SS_Index; |
| -- Create a scenario where the frame index of the secondary stack overflows |
| -- while the stack itself uses little memory. |
| |
| ----------------------- |
| -- Overflow_SS_Index -- |
| ----------------------- |
| |
| procedure Overflow_SS_Index is |
| Max_Iterations : constant := 20_000; |
| -- The approximate number of iterations needed to overflow the frame |
| -- index type on a 64bit target. |
| |
| Algn : constant Positive := Positive (Standard'Maximum_Alignment); |
| -- The maximum alignment of the target |
| |
| Size : constant Positive := Positive (Runtime_Default_Sec_Stack_Size); |
| -- The default size of the secondary stack on the target |
| |
| Base_Str : constant String (1 .. Size) := (others => 'a'); |
| -- A string big enough to fill the static frame of the secondary stack |
| |
| Small_Str : constant String (1 .. Algn) := (others => 'a'); |
| -- A string small enough to cause a new round up to the nearest multiple |
| -- of the maximum alignment on the target at each new iteration of the |
| -- loop. |
| |
| Base_US : Unbounded_String := To_Unbounded_String (Base_Str); |
| -- Unbounded version of the base string |
| |
| procedure SS_Print is new SS_Info (Put_Line); |
| |
| begin |
| for Iteration in 1 .. Max_Iterations loop |
| |
| -- Grow the base string by a small amount at each iteration of the |
| -- loop. |
| |
| Append (Base_US, Small_Str); |
| |
| -- Convert the unbounded base into a new base. This causes routine |
| -- To_String to allocates the new base on the secondary stack. Since |
| -- the new base is slignly bigger than the previous base, the stack |
| -- would have to create a new frame. |
| |
| -- Due to an issue with frame reclamation, the last frame (which is |
| -- also not big enough to fit the new base) is never reclaimed. This |
| -- causes the range of the new frame to shift toward the overflow |
| -- point of the frame index type. |
| |
| begin |
| declare |
| New_Base_Str : constant String := To_String (Base_US); |
| begin null; end; |
| |
| exception |
| when Storage_Error => |
| Put_Line ("ERROR: SS depleted"); |
| Put_Line ("Iteration:" & Iteration'Img); |
| Put_Line ("SS_Size :" & Size'Img); |
| Put_Line ("SS_Algn :" & Algn'Img); |
| |
| SS_Print; |
| exit; |
| |
| when others => |
| Put_Line ("ERROR: unexpected exception"); |
| exit; |
| end; |
| end loop; |
| end Overflow_SS_Index; |
| |
| -- Start of processing for SS_Depletion |
| |
| begin |
| -- This issue manifests only on targets with a dynamic secondary stack |
| |
| if Sec_Stack_Dynamic then |
| Overflow_SS_Index; |
| end if; |
| end Sec_Stack2; |