大型阵列会引发错误的内存访问ada

时间:2014-03-22 00:36:12

标签: ada

有没有办法让这段代码有效?我想创建一个大小为10mio的数组。地址。但是运行此代码会引发* CONSTRAINT_ERROR:错误的内存访问*。

procedure Main is
   type A_Type is abstract tagged null record;

   type B_Type is new A_Type with null record;
   type B_Type_Access is access all B_Type;

   type C is array (1 .. 10_000_000) of B_Type_Access;
   D : C;
begin
   null;
end Main;

3 个答案:

答案 0 :(得分:4)

我猜测堆栈中变量D的创建太多了。尝试在池中创建一组访问变量,如下所示:

PROCEDURE Main IS
   TYPE A_Type IS ABSTRACT TAGGED NULL RECORD;

   TYPE B_Type IS NEW A_Type WITH NULL RECORD;
   TYPE B_Type_Access IS ACCESS ALL B_Type;

   TYPE C IS ARRAY (1 .. 10_000_000) OF B_Type_Access;
   TYPE E IS ACCESS C;
   D : E;
BEGIN
   D := NEW C;


END Main;

答案 1 :(得分:2)

Herr_Doktor有一个很好的解决方案。另一个是将数组(和所有类型)放在一个包中(我假设Main不会递归调用自身):

package Main_Package is
    procedure Main;
end Main_Package;

package body Main_Package is

    type A_Type is abstract tagged null record;

    type B_Type is new A_Type with null record;
    type B_Type_Access is access all B_Type;

    type C is array (1 .. 10_000_000) of B_Type_Access;
    D : C;

    procedure Main is
    begin
        -- whatever you were going to do
    end Main;

end Main_Package;

with Main_Package;
procedure Main is
begin
    Main_Package.Main;
end Main;

现在,由于数组C不再在一个过程中,它将被分配在常规数据存储器而不是堆栈中。

答案 2 :(得分:1)

Ada中的变量通常在堆栈上分配。这意味着您必须确保允许您的进程为您声明的变量设置足够大的堆栈。

在Linux系统上,您可以使用ulimit命令更改堆栈进程的大小:

% cat main.adb
procedure Main is
   type A_Type is abstract tagged null record;

   type B_Type is new A_Type with null record;
   type B_Type_Access is access all B_Type;

   type C is array (1 .. 10_000_000) of B_Type_Access;
   D : C;
begin
   null;
end Main;
% gnatmake -gnato -gnata -fstack-check main.adb
[...]

使用足够的堆栈空间运行它:

% ulimit -s 90000
% ./main
% echo $?
0

用太小的堆栈空间运行它:

% ulimit -s 9000
% ./main

raised STORAGE_ERROR : stack overflow (or erroneous memory access)
% echo $?
1