Как отлаживать ACSL в frama-c?

81
7

Я пытаюсь узнать ACSL, но споткнулся, пытаясь написать полную спецификацию. Мой код

#include <stdint.h>
#include <stddef.h>

#define NUM_ELEMS (8)

/*@ requires expected != test;
@ requires \let n = NUM_ELEMS;
@ \valid_read(expected + (0.. n-1)) && \valid_read(test + (0.. n-1));
@ assigns \nothing;
@ behavior matches:
@ assumes \let n = NUM_ELEMS;
@ \forall integer i; 0 <= i < n ==> expected[i] == test[i];
@ ensures \result == 1;
@ behavior not_matches:
@ assumes \let n = NUM_ELEMS;
@ \exists integer i; 0 <= i < n && expected[i] != test[i];
@ ensures \result == 0;
@ complete behaviors;
@ disjoint behaviors;
@*/
int array_equals(const uint32_t expected[static NUM_ELEMS], const uint32_t test[static NUM_ELEMS]) {
for (size_t i = 0; i < NUM_ELEMS; i++) {
if (expected[i] != test[i]) {
return 0;
}
}
return 1;
}

Я запускаю его с помощью

frama-c -wp -wp -rte test.c

и я вижу следующий журнал

[kernel] Parsing FRAMAC_SHARE/libc/__fc_builtin_for_normalization.i (no preprocessing)
[kernel] Parsing test.c (with preprocessing)
[rte] annotating function array_equals
test.c:22:[wp] warning: Missing assigns clause (assigns 'everything' instead)
[wp] 9 goals scheduled
[wp] [Alt-Ergo] Goal typed_array_equals_assign_part1 : Unknown (Qed:2ms) (67ms)
[wp] [Alt-Ergo] Goal typed_array_equals_assert_rte_mem_access_2 : Unknown (Qed:2ms) (128ms)
[wp] [Alt-Ergo] Goal typed_array_equals_assert_rte_mem_access : Unknown (Qed:2ms) (125ms)
[wp] [Alt-Ergo] Goal typed_array_equals_matches_post : Unknown (Qed:10ms) (175ms)
[wp] [Alt-Ergo] Goal typed_array_equals_not_matches_post : Unknown (Qed:7ms) (109ms)
[wp] Proved goals: 4 / 9
Qed: 4 (0.56ms-4ms)
Alt-Ergo: 0 (unknown: 5)

Поэтому мне кажется, что мои два поведения и "присваивает\ничего" не могут быть доказаны. Итак, как я исхожу отсюда?

EDIT: Итак, я понял, что проблема. У меня нет аннотированной моей циклы:

  /*@ loop invariant \let n = NUM_ELEMS; 0 <= i <= n;
@ loop invariant \forall integer k; 0 <= k < i ==> expected[k] == test[k];
@ loop assigns i;
@ loop variant \let n = NUM_ELEMS; n-i;
@*/

Мой более крупный вопрос по-прежнему стоит: какой хороший способ отладить проблемы? Я решил это, просто изменив и удалив код и увидев, что доказано/не доказано.

спросил(а) 2017-07-20T02:20:00+03:00 3 года, 3 месяца назад
1
Решение
82

Боюсь, не может быть окончательного ответа на этот вопрос (честно говоря, я решил голосовать, чтобы закрыть его как "слишком широкий"). Вот, однако, несколько рекомендаций, которые, вероятно, помогут вам в ваших попытках доказательства:

Определение отдельных статей

Спецификации ACSL быстро состоят из множества предложений (requires, ensures, loop invariant, assert ,...). Важно иметь возможность легко различать их. Для этого у вас есть два основных ингредиента:

Используйте графический интерфейс. Это значительно упрощает представление, какие аннотации доказаны (зеленая пуля), доказано, но при условии, что другие, недоказанные условия верны (зеленые/желтые) или недоказанные (желтые). Назовите свои предложения: любому предикату ACSL можно прикрепить имя с name: pred синтаксиса name: pred. Когда предложение снабжено именем, WP будет использовать его для ссылки на предложение. Обычные подозреваемые

Очень легко пропустить очень важную часть спецификации. Вот список быстрых проверок:

Все циклы должны быть оснащены loop invariant а loop assigns Все функции, которые вызываются по одному при анализе должны иметь договор (по крайней мере, assigns п) Если ячейка памяти, упомянутая в назначении loop assigns не является объектом соответствующего loop invariant, вы ничего не знаете о значении, хранящемся в этом месте вне цикла. Это может быть проблемой. Отладка отдельных статей

Как только вы уверены, что не пропустили ничего очевидного, пришло время начать расследование по отдельным статьям.

Как правило, гораздо проще проверить, что loop invariant установлен (т.е. Истинно при достижении цикла в первый раз), а не сохраняется (оставаясь верным на шаге цикла). Если вы не можете установить loop invariant, это либо неправильно, либо вы забыли, что некоторые из них requires ограничения ввода функции (типичный случай для алгоритма над массивами является loop invariant 0<=i<=n; что не может если вы не requires n>=0;) Точно так же assigns и назначения loop assigns должны быть легче проверяться, чем реальные функциональные свойства. Пока они не все доказаны, вы должны сосредоточиться на них (общая ошибка заключается в том, чтобы забыть указать индекс цикла в его loop assigns или упомянуть, что он назначает a[i] а не a[0..i]). Не забывайте, что assigns должны включать в себя все возможные назначения, в том числе тех, которые сделаны в вызываемые методы. Не стесняйтесь использовать assert чтобы проверить, может ли WP доказать, что свойство имеет место в данной точке. Это поможет вам понять, где возникают проблемы. [Править в соответствии с @DavidMENTRÉ комментарий ниже] Обратите внимание, что в этом случае, вы должны позаботиться о том, что первоначальное доказательство обязательство может преуспеть в предположении, что assert, имеет место в то время как assert само по себе не подтверждено. В GUI это отражается зеленой/желтой пулей и, конечно же, желтой пулей перед assert. В этом случае доказательство еще не закончено, и вы должны понять, почему утверждение не доказано, возможно, используя ту же стратегию, что и выше, до тех пор, пока вы не поймете, где именно лежит проблема.

ответил(а) 2017-07-20T11:16:00+03:00 3 года, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема