证明在SPARK中初始化了从数组中读取的内容

时间:2014-09-02 17:14:43

标签: ada

给出一个非常简单的SPARK函数,它对一个整数数组求和:

function Add (X, Y : in Ints) return Ints is
   Sum : Ints;
begin
   for i in Ints'Range loop
      pragma Loop_Invariant (for all j in Ints'First .. i - 1 => Sum(j) = X(j) + Y(j));  -- line 7
      Sum(i) := X(i) + Y(i);
   end loop;

   return Sum;  -- line 11
end Add;

type Ints is array (Integer range 0 .. 9) of Integer_32

没有循环不变的编译工作正常(因为我有一个前提条件,它限制XY的元素,这样就不会发生溢出。但是,为了显示post条件的某些属性,我需要不变量,但结果是:

7:69: warning: "Sum" may be referenced before it has a value
Phase 2 of 3: analysis and translation to intermediate language ...
7:10: "Sum" is not initialized
11:7: warning: "Sum" might not be initialized

我不确定"初始化的概念"用证明语言表达,所以我不知道如何说服gnatprove没有发生未初始化的读数。

我可以通过在功能开始时将Sum的所有元素明确设置为零来删除警告,但我希望有更好的方法。

1 个答案:

答案 0 :(得分:4)

在SPARK中,数组被视为整个对象,并且不允许像您一样进行逐个组件的初始化。但是,gnatprove中有一个启发式方法,允许在数组范围内进行简单的for循环,就像你一样。这就是为什么没有循环不变量,你就不会收到警告。这种启发式方法因循环不变而崩溃,这就是为什么你再次收到警告的原因。

您必须使用编译指示警告接受警告,如下所述:

https://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Warnings.html

为了避免你在第7行得到的错误,你可以在赋值后移动循环不变量(并相应地改变量化的范围)。