The SEGFAULT
in your second example comes most certainly from the initialization.
Compare
type Short_Array is array (Natural range <>) of Short;
Items : access Short_Array;
Items := new Short_Array(1..UpperBound);
Items.all := (others => 0);
And this:
type Short_Array is array (Natural range <>) of Short;
Items : access Short_Array;
Items := new Short_Array(1..UpperBound);
for I in 1..UpperBound loop
Items(I) := 0;
end loop;
And play with different values of ulimit -Ss
which sets the allowed size of the stack.
The point is that
Items.all := (others => 0);
allocates an array on the stack and copy it in your heap-allocated array. So you think you are working on the heap but still needs a lot of stack. If your array is too big for your ulimit -Ss
(or considering both soft and hard limits ulimit -s
), you will segfault (or get a STORAGE_ERROR
) though you think you are all on the heap.
To mitigate this problem, (though it might not work in every situation, eg if UpperBound
is dynamic…), you can compile your code either with:
"-fstack-usage"
(to get usage information for each unit)
"-Wstack-usage=2000"
(or any limit more accurate to your case, see gnat's documentation for more infos) to yield warnings for functions using too much stack (or having unbounded stack usage).
The second option could have issued a warning and pointed you to your stack overflow.