[英]Why does the dependence graph of this scanf()-using program by Frama-C look like this?
我使用Frama-C工具生成此程序的依賴圖(main.c)。
#include<stdio.h>
int main()
{
int n,i,m,j;
while(scanf("%d",&n)!=EOF)
{
m=n;
for(i=n-1;i>=1;i--)
{
m=m*i;
while(m%10==0)
{
m=m/10;
}
m=m%10000;
}
m=m%10;
printf("%5d -> %d\n",n,m);
}
return 0;
}
該命令是:
frama-c -pdg -dot-pdg main main.c
dot -Tpdf main.main.dot -o main.pdf
結果是 我的問題是為什么陳述“ m = m * i;”,“ m = m%10000”沒有映射到節點。 結果似乎不正確,因為代碼中存在三個循環。
僅當C程序的切片器定義的目標是保留定義的執行 ,並且允許切片器更改未定義的執行時 ,切片器才在實踐中起作用。
否則,切片器將無法刪除諸如x = *p;
的語句x = *p;
一旦無法確定p
是有效的指針,即使它知道不需要x
,也就是因為即使刪除了該語句,該處p
為NULL的執行也會更改。
Frama-C不處理復雜的庫函數,如scanf()
。 因此,它認為使用局部變量n
無需初始化。
鍵入frama-c -val main.c
您應該收到類似以下的警告:
main.c:10:[kernel] warning: accessing uninitialized left-value:
assert \initialized(&n);
...
[value] Values for function main:
NON TERMINATING FUNCTION
“ assert
”一詞意味着Frama-C的選項-val
無法確定所有執行均已定義,而“ NON TERMINATING FUNCTION”意味着無法找到要繼續執行的程序的單個已定義執行。
PDG刪除大多數語句的原因是未初始化變量的未定義使用。 PDG算法認為它可以刪除它們,因為它們遵循它認為是未定義的行為,即對變量n
的首次訪問。
我稍稍修改了程序,用一個更簡單的語句替換了scanf()
調用:
#define EOF (-1)
int unknown_int();
int scan_unknown_int(int *p)
{
*p = unknown_int();
return unknown_int();
}
int main()
{
int n,i,m,j;
while(scan_unknown_int(&n) != EOF)
{
m=n;
for(i=n-1;i>=1;i--)
{
m=m*i;
while(m%10==0)
{
m=m/10;
}
m=m%10000;
}
m=m%10;
printf("%5d -> %d\n",n,m);
}
return 0;
}
我在下面看到了PDG。 據我所知,它看起來很完整。 如果您知道比dot
更好的布局程序但可以接受dot
格式,那么這是使用它們的好機會。
請注意,最外層的條件while
成為tmp != -1
。 圖的節點是程序內部歸一化表示的語句。 條件tmp != -1
對語句tmp = unknown_int();
的節點具有數據依賴性tmp = unknown_int();
。 您可以使用frama-c -print main.c
顯示內部表示,它將顯示最外層的循環條件已分解為:
while (1) {
int tmp;
tmp = scan_unknown_int(& n);
if (! (tmp != -1)) { break; }
除其他事項外,這有助於切片僅刪除復雜語句中可以刪除的部分,而不必保留整個復雜語句。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.