【问题标题】:Ada Record Initialization: "Constraint_Error"Ada 记录初始化:“Constraint_Error”
【发布时间】:2018-04-18 17:30:39
【问题描述】:

我正在尝试在记录中插入新元素。我在记录中设置了默认值并查找了如何初始化记录,但编译器一直说,“警告:此处不允许空值”,“警告:'Constraint_Error' 将在运行时引发。”以下是我正在处理的块。

type employee;
type employeePtr is access employee;
type employee is
record
  id : Integer := 0;
  name : Unbounded_String := To_Unbounded_String("");
  departmentname : Unbounded_String := To_Unbounded_String("");
  jobtitle : Unbounded_String := To_Unbounded_String("");
  payrate : Unbounded_String := To_Unbounded_String("");
  next : employeePtr := null;
end record;

employeeList : employeePtr;

procedure insertNew(employeeid : Unbounded_String; employeename : Unbounded_String; department : Unbounded_String; title : Unbounded_String; rate : Unbounded_String) is
  currentEmployee : employeePtr;
  --tmp : employeePtr := employeePtr'(id => 0, name => "", departmentname => "", jobtitle => "", payrate => "");
  tmp : employeePtr;
  tmpSkp : employeePtr;
  eid : Integer;
  placeAtEnd : Integer;
begin
  eid := Integer'Value(To_String(employeeid));
  tmp.id := eid;
  tmp.name := employeename;
  tmp.departmentname := department;
  tmp.jobtitle := title;
  tmp.payrate := rate;

  if employeeList.id = 0 then
     employeeList := tmp;
  else
     placeAtEnd := 1;
     while currentEmployee.next /= null loop
        if currentEmployee.next.id > eid then
           tmpSkp := currentEmployee.next;
           tmp.next := tmpSkp;
           currentEmployee.next := tmp;
           placeAtEnd := 0;
           exit;
        else
           currentEmployee := currentEmployee.next;
        end if;
     end loop;
     if placeAtEnd = 1 then
        currentEmployee.next := tmp;
     end if;
  end if;
end insertNew;

begin 之后,我试图设置 tmp 成员的值,是我得到这些错误的地方。 我是否错误地初始化了记录?有没有类似于 Java 中的 try/catch 的东西可以解决这个问题?

【问题讨论】:

  • (显然不适用于您的情况,但我会在此处将此评论留给其他收到相同错误消息的人)该错误消息通常来自显式(或在编译时可检测到)分配 @987654322 @to 一个 not null 访问类型的值
  • 这是家庭作业/学习练习吗?因为否则正确的方法是使用 Ada.Containers.Doubly_Linked_Lists 的实例化。

标签: warnings record ada


【解决方案1】:

使用-gnatl 编译(在包装器内,因此行号相差 3)给出

21.       tmp : employeePtr;

所有访问变量都默认初始化为null。我会写的

          tmp : constant employeePtr := new employee;

constant 因为你不会改变指针,只是它指向的东西)。

回到代码,

27.       tmp.id := eid;
          |
    >>> warning: null value not allowed here
    >>> warning: "Constraint_Error" will be raised at run time

因为Constraint_Error 是通过空指针访问所需的运行时错误。

28.       tmp.name := employeename;
          |
    >>> warning: null value not allowed here
    >>> warning: "Constraint_Error" will be raised at run time

29.       tmp.departmentname := department;
          |
    >>> warning: "tmp" may be null

我认为编译器已停止向重复警告添加细节。

30.       tmp.jobtitle := title;
31.       tmp.payrate := rate;

现在它完全停止了警告。

【讨论】:

    【解决方案2】:

    我不知道 new 是 Ada 中的东西,但这就是问题所在。与 malloc 类似,为了初始化记录的实例,您使用关键字 new,就像在 Java 中一样。

    【讨论】:

    • 你只在处理访问类型时使用new(类似于C中的指针,但不完全是),比如你的employeePtr