为什么无限循环在使用Promela和Spin进行模型检查时不会导致错误?

时间:2019-10-17 22:31:04

标签: model-checking promela spin

如果我在Promela中编写以下代码并以验证程序模式在Spin中运行,则它将以0错误结束。它确实报告toogleinit处于未到达状态,但是这些似乎只是警告。

byte x = 0; byte y = 0;
active proctype toggle() {
    do
    :: x == 1 -> x = 0
    :: x == 0 -> x = 1
    od
}
init {
    (y == 1);
}

我对此感到困惑,因为我认为这会给我一个“无效的结束状态”错误。如果我用简单的skip语句更改 toogle proctype的主体,它确实会出错误,如我所愿。

这是为什么?有没有办法强迫模拟器将无限循环报告为错误?

关于“未到达proctype”消息,在end循环中添加do标签似乎没有任何作用。

我正在运行spin 6.5.0,并运行以下命令:

spin.exe -a test.pml
gcc -o pan pan.c
pan.exe

这些是输出,以供参考。

使用do循环:

pan.exe

(Spin Version 6.5.0 -- 1 July 2019)
        + Partial Order Reduction

Full statespace search for:
        never claim             - (none specified)
        assertion violations    +
        acceptance   cycles     - (not selected)
        invalid end states      +

State-vector 20 byte, depth reached 3, errors: 0
        4 states, stored
        1 states, matched
        5 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000       equivalent memory usage for states (stored*(State-vector + overhead))
    0.292       actual memory usage for states
   64.000       memory used for hash table (-w24)
    0.343       memory used for DFS stack (-m10000)
   64.539       total actual memory usage


unreached in proctype toggle
        ..\test2.pml:7, state 8, "-end-"
        (1 of 8 states)
unreached in init
        ..\test2.pml:10, state 2, "-end-"
        (1 of 2 states)

pan: elapsed time 0.013 seconds
pan: rate 307.69231 states/second

使用skip

pan.exe
pan:1: invalid end state (at depth 0)
pan: wrote ..\test2.pml.trail

(Spin Version 6.5.0 -- 1 July 2019)
Warning: Search not completed
        + Partial Order Reduction

Full statespace search for:
        never claim             - (none specified)
        assertion violations    +
        acceptance   cycles     - (not selected)
        invalid end states      +

State-vector 20 byte, depth reached 1, errors: 1
        2 states, stored
        0 states, matched
        2 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000       equivalent memory usage for states (stored*(State-vector + overhead))
    0.293       actual memory usage for states
   64.000       memory used for hash table (-w24)
    0.343       memory used for DFS stack (-m10000)
   64.539       total actual memory usage



pan: elapsed time 0.015 seconds
pan: rate 133.33333 states/second

1 个答案:

答案 0 :(得分:2)

在此示例中

byte x = 0; byte y = 0;
active proctype toggle() {
    do
    :: x == 1 -> x = 0
    :: x == 0 -> x = 1
    od
}
init {
    (y == 1);
}

init进程将永远被阻止(因为y == 1始终为false),但是toggle进程始终可以执行某事。因此,不会出现没有 无效的结束状态错误

在此示例中,

byte x = 0; byte y = 0;
active proctype toggle() {
    skip;
}
init {
    (y == 1);
}

init进程仍然被永远阻止,但是toggle进程可以执行其唯一的指令skip;,然后终止。此时,其余进程(即仅init)都没有可执行的指令,因此Spin无效的结束状态错误终止。

~$ spin -a -search test.pml
pan:1: invalid end state (at depth 0)
pan: wrote test.pml.trail

(Spin Version 6.5.0 -- 17 July 2019)
...
State-vector 20 byte, depth reached 1, errors: 1
...

  

是否有一种方法可以强制模拟器将无限循环报告为错误?

是的。实际上有多种方法。

最简单的方法是使用Spin的选项-l

~$ spin --help
...
-l: search for non-progress cycles
...

使用此选项,Spin会报告任何无限循环,其中不包含带有progress标签的任何状态。

这是您原始问题的输出:

~$ spin -search -l test.pml
pan:1: non-progress cycle (at depth 2)
pan: wrote test.pml.trail

(Spin Version 6.5.0 -- 17 July 2019)
...
State-vector 28 byte, depth reached 9, errors: 1
...

~$ spin -t test.pml
spin: couldn't find claim 2 (ignored)
  <<<<<START OF CYCLE>>>>>
spin: trail ends after 10 steps
#processes: 2
        x = 0
        y = 0
 10:    proc  1 (:init::1) test.pml:10 (state 1)
 10:    proc  0 (toggle:1) test.pml:5 (state 4)
2 processes created

另一种方法是使用LTL模型检查。例如,您可能会指出,在某些时候,正在执行的进程数(请参见 _nr_pr )等于0(或者,如果您承认一些无限循环),或使用remote references检查特定进程是否正确终止。

以下示例均包含这两种情况:

byte x = 0; byte y = 0;
active proctype toggle() {
    do
    :: x == 1 -> x = 0
    :: x == 0 -> x = 1
    od;
end:
}
init {
    (y == 1);
}

// sooner or later, the process toggle
// with _pid == 0 will reach the end
// state
ltl p1 { <> toggle[0]@end };

// sooner or later, the number of processes
// that are currently running becomes 0,
// (hence, there can be no infinite loops)
ltl p2 { <> (_nr_pr == 0) };

第一个

~$ spin -a -search -ltl p1 test.pml
~$ spin -t test.pml
ltl p1: <> ((toggle[0]@end))
ltl p2: <> ((_nr_pr==0))
  <<<<<START OF CYCLE>>>>>
Never claim moves to line 4 [(!((toggle[0]._p==end)))]
spin: trail ends after 8 steps
#processes: 2
        x = 0
        y = 0
        end = 0
  8:    proc  1 (:init::1) test.pml:10 (state 1)
  8:    proc  0 (toggle:1) test.pml:3 (state 5)
  8:    proc  - (p1:1) _spin_nvr.tmp:3 (state 3)
2 processes created

第二个

~$ spin -a -search -ltl p2 test.pml
~$ spin -t test.pml
ltl p1: <> ((toggle[0]@end))
ltl p2: <> ((_nr_pr==0))
  <<<<<START OF CYCLE>>>>>
Never claim moves to line 11    [(!((_nr_pr==0)))]
spin: trail ends after 8 steps
#processes: 2
        x = 0
        y = 0
        end = 0
  8:    proc  1 (:init::1) test.pml:10 (state 1)
  8:    proc  0 (toggle:1) test.pml:3 (state 5)
  8:    proc  - (p2:1) _spin_nvr.tmp:10 (state 3)
2 processes created

发现LTL属性为假。


  

关于“未到达proctype”消息,在do循环中添加结束标签似乎无济于事。

end标签用于删除 “无效的最终状态” 错误,否则可能会找到了。

例如,如下修改您的上一个示例:

byte x = 0; byte y = 0;
active proctype toggle() {
    skip;
}

init {
end:
    (y == 1);
}

使错误消失:

~$ spin -a -search test.pml
(Spin Version 6.5.0 -- 17 July 2019)
...
State-vector 20 byte, depth reached 1, errors: 0
...

仅当一个人愿意保证一个进程被卡住而没有可执行指令不是不希望出现的死锁情况时,才应该使用end标签。