I am trying to use the 'Last
attribute with a 2D array in Ada, but I can't seem to find the correct syntax to do so.
I know that if I have a 1D array/vector I can use A'last or A'last(n) where n is the nth dimension. But if I do the following
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
end temp;
I get the following compile time error:
Storage_Error stack overflow (or erroneous memory access)
So what am I doing wrong?
I am using GNAT Pro 6.4.1 on Linux.
I'd be very surprised if you got a compile-time Storage_Error
on that code.
I've grabbed a copy of your code and modified it as follows; it compiles without error using GNAT (gcc-4.4):
procedure Array_2D is
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
return 42; -- added this
end temp;
begin
null;
end Array_2D;
(Note that I had to add the missing return
statement in temp
.)
Your syntax for the 'Last
attribute (not "command") is correct, but since Ada arrays can have arbitrary lower and upper bounds, it's better to use the 'Range
attribute instead:
for i in tempTable'Range(1) loop
for j in tempTable'Range(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
As for the Storage_Error
exception, that could easily happen at run time (not compile time) if you call your temp
function with a very large value for tempIn
. Remember that it has to allocate enough space to hold tempIn**2
Integer
objects. Presumably you've also created another UnconstrainedArray_2D
object to be passed in as the Table
parameter.
It's conceivable that the compiler itself could die with a Storage_Error
exception, but I don't see anything in your code that might cause that.
Show us a complete (but small) program that demonstrates the problem you're having, along with the exact (copy-and-pasted) error message. Please distinguish clearly between compile-time and run-time errors.
Thank you for the example. The error I get is definately at compile time and I have found that if I change type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
to type UnconstrainedArray_2D is array (Integer range 0..Integer'last, Integer range 0..Integer'last) of Integer;
then the Storage_Error disappers - Fred 2012-04-04 22:29
compilation abandoned
gnatmake: "file.adb" compilation error
Fred 2012-04-04 22:34
Storage_Error
in that message. There should be a message from the compiler itself, referring to a specific line in file.adb
- Keith Thompson 2012-04-04 22:56
Your tempTable
might have a range of 0..tempIn
, but you don't know what range your Table
has.. They could be of different length, too.
You would have to check that the length is the same and then use relative indices, like this:
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
if tempTable'Length (1) /= Table'Length (1) or else
tempTable'Length (2) /= Table'Length (2)
then
raise Constraint_Error; -- or something else
end if;
for i in 0 .. tempTable'Length (1) - 1 loop
for j in 0 .. tempTable'Length (2) - 1 loop
tempTable(tempTable'First (1) + i, tempTable'First (2) + j) :=
Table(Table'First (1) + i, Table'First (2) + j);
end loop;
end loop;
end temp;
that way it is ensured that both tables are same length and all indices are valid.
If your tempTable
is allowed to be smaller than Table
, simply adjust the length check to >
. The indices would still be valid.
I don't see an actual value for tempIn set. If the value for tempIn coming into the function temp has not been properly initialized or explicitly set, then the value in tempIn could be anything and probably not something you would like.
I was thinking of a default value. (probably shouldn't post when I am not feeling well :-)
tempIn
? This is a function declaration, not a function call - Simon Wright 2012-04-06 21:57
Table : in UnconstrainedArray_2D
in the function. But I'm still not sure what I have done wrong - Fred 2012-04-04 20:21