Заставить Frama-c показывать зависимости даже от "мертвых веток"
Я использую версию frama-c Aluminium-20160502 и хочу выяснить зависимости в большой программе. При использовании опции -deps в командной строке я обнаружил, что некоторые зависимости отсутствуют. В частности, когда несколько условий объединяются в одно условие if, анализ зависимостей останавливается всякий раз, когда одно условие ложно. В этом примере здесь:
#include<stdio.h>
#include<stdbool.h>
/*Global variable definitions*/
bool A = true;
bool B = false;
bool C = true;
bool X;
bool Y;
bool res;
void main(){
if (A && B && C) {
res = X;
}else res = Y;
}
когда я пытаюсь: frama-c -deps program.c
frama показывает следующие зависимости:
[из] ====== Зависимости вычислены ======
Эти зависимости сохраняются при завершении для выполнений, которые заканчиваются:
[from] Функция main: res ОТ A; B; Y
[из] ====== КОНЕЦ ЗАВИСИМОСТИ ======
поэтому он не достигает условия C, потому что уже B ложно.
Интересно, есть ли способ сказать frama для вычисления всех зависимостей, даже если условие не выполняется. Я попытался с опцией -slevel, но безрезультатно. Я знаю, что есть способ использовать интервал Frama_C_interval(0,1), но когда я использую его, переменная, использующая эту функцию, не отображается в зависимостях. Я хотел бы, чтобы X и Y зависели от A,B,C и res зависели от A,B,C,X,Y
Есть идеи?
1 ответ
Плагин From использует результаты плагина анализа значений. В вашем примере значения A
а также B
достаточно точны, что Значение может сделать вывод, что условие полностью определено (так как &&
оператор лениво оценивается, слева направо) до достижения C
, следовательно C
никогда не влияет на результат и, следовательно, не является зависимостью с точки зрения От.
К несчастью, Frama_C_interval
нельзя использовать напрямую в глобальных инициализаторах:
user error: Call to Frama_C_interval in constant.
Вы можете, однако, использовать "хак" (не всегда лучшее решение, но работает здесь):
volatile bool nondet;
bool A = nondet;
bool B = nondet;
bool C = nondet;
...
Обратите внимание, что, потому что nondet
является volatile
каждая переменная A
, B
а также C
назначается другое недетерминированное значение.
В этом случае Value должен учитывать обе ветви условных выражений, и поэтому C
становится зависимостью в вашем примере, так как возможно, что C
будет прочитано во время исполнения main
, Вы тогда будете иметь:
These dependencies hold at termination for the executions that terminate:
[from] Function main:
res FROM A; B; C; X; Y
Обратите внимание, что некоторые плагины требуют особой обработки при работе с переменными переменными, поэтому это не всегда лучшее решение.
Это, однако, имеет дело только с некоторыми видами зависимостей. Как упомянуто в главе 6 руководства пользователя Value Analysis, плагин From вычисляет функциональные, императивные и эксплуатационные зависимости. Они не включают косвенные зависимости управления, такие как X from A, B, C
, как вы упоминаете. Для этого вам понадобится плагин PDG (График зависимостей программы), но в настоящее время он не имеет текстового вывода зависимостей. Ты можешь использовать -pdg
вычислить это, а затем -pdg-dot <file>
экспортировать граф зависимостей в формате dot (graphviz). Вот что я получу за ваш main
функция (используя изменчивый хак, как упоминалось ранее):
Наконец, в качестве примечания: -slevel
в основном используется для повышения точности, но в вашем примере у вас уже есть слишком высокая точность (т. е. Value уже может сделать вывод, что C
никогда не читается внутри main
).