用于初始化动态分配数组的 Ada 语法

Ada Syntax for initializing dynamically allocated array

在 Ada 中初始化动态分配数组的正确语法是什么?我试过这个:

type Short_Array is array (Natural range <>) of Short;
Items : access Short_Array;
Items := new Short_Array(1..UpperBound)'(others => 0);

这会导致编译器错误 - "binary operator expected"。还有这个:

type Short_Array is array (Natural range <>) of Short;
Items : access Short_Array;
Items := new Short_Array(1..UpperBound);
Items.all := (others => 0);

这似乎令人惊讶地引发了 SEGFAULT。不确定那里发生了什么,但想在开始追尾之前获得正确的语法。

如果您使用的是 Ada2012,您可以执行以下操作:

type Short_Array is array(Natural range <>) of Short with
   Default_Component_Value => 0;
Items : access Short_Array := new Short_Array(1..UpperBound);

Ada 2012 基本原理第 2.6 节解释了数组默认初始值的使用 http://www.ada-auth.org/standards/12rat/html/Rat12-2-6.html

Ada 中的另一种方法是将记录定义为判别式记录,判别式决定数组字段的大小。

type Items_Record (Size : Natural) is record
   -- Some non-array fields of your record
   Items : Short_Array(1..Size);
end record;

然后可以在内部块中分配记录的实例

Get(Items_Size);
declare
   My_Record : Items_Record(Size => Items_Size);
begin
   -- Process the instance of Items_Record
end;

记录是在堆栈上动态分配的。如果记录大小非常大,您将遇到堆栈溢出问题。如果没有,这很好用。这种方法的一个优点是,当到达块末尾时,实例会自动取消分配。

第二个示例中的 SEGFAULT 肯定来自初始化。

比较

type Short_Array is array (Natural range <>) of Short;
Items : access Short_Array;
Items := new Short_Array(1..UpperBound);
Items.all := (others => 0);

还有这个:

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;

并使用不同的 ulimit -Ss 值来设置允许的堆栈大小。

重点是

Items.all := (others => 0);

在堆栈上分配一个数组并将其复制到堆分配的数组中。所以你认为你在堆上工作但仍然需要很多堆栈。如果你的数组对于你的 ulimit -Ss 来说太大了(或者考虑到软限制和硬限制 ulimit -s),你会出现段错误(或者得到一个 STORAGE_ERROR),尽管你认为你都在堆上.

为了缓解这个问题,(虽然它可能不是在所有情况下都有效,例如如果UpperBound是动态的......),你可以编译你的代码:

  • "-fstack-usage"(获取每个单元的使用信息)
  • "-Wstack-usage=2000"(或对您的情况更准确的任何限制,请参阅 gnat's documentation 了解更多信息)以对使用过多堆栈(或无限堆栈使用)的函数发出警告。

第二个选项可能会发出警告并指出您的堆栈溢出。