簡體   English   中英

為什么Frama-C的使用scanf()的程序的依賴圖看起來像這樣?

[英]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格式,那么這是使用它們的好機會。

復合PDG 請注意,最外層的條件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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM