有没有一种方法可以对C代码进行语法/语义差异比较?

3

NEC2最初是用Fortran编写的,并从原始Fortran进行了两个不同的C端口(xnec2cnecpp)。

变量和函数名称相似(通常完全相同)。然而,作者选择了不同的数据结构来存储全局值。

是否有一种方法可以对这两个实现进行差异比较,以查看是否存在实际差异,而不仅仅是命名约定上的差异?

似乎可能是可行的,重构工具如Coccinelle具有一定的结构意识并理解数据类型。

如果是这样,那么通过这样的静态分析可以检测到由于作者错误导致的一个程序或另一个程序中的错误。然后,人们可以将C代码实现与原始Fortran进行比较,以确定哪一个是正确的,或者如果在语法上不同的表示是计算等效的。请注意,这是一个静态分析,我们只想知道代码结构(分支和表达式,因此数据类型)是否相同。

例如,这两个示例计算相同的内容,但变量icon1ind1的存储不同:

     if( -icon1[iprx] != jx )
        ind1=2;
      else
      {
        xi= fabsl( cabj* cab[iprx]+ sabj* sab[iprx]+ salpj* salp[iprx]);
        if( (xi < 0.999999) || (fabsl(bi[iprx]/b-1.) > 1.e-6) )
          ind1=2;
        else
          ind1=0;
      }

比较

      if( -data.icon1[iprx] != jx )                       
        dataj.ind1=2;                                     
      else                                                
      {                                                   
        xi= fabs( dataj.cabj* data.cab[iprx]+ dataj.sabj* 
            data.sab[iprx]+ dataj.salpj* data.salp[iprx]);
        if( (xi < 0.999999) ||                            
            (fabs(data.bi[iprx]/dataj.b-1.0) > 1.0e-6) )  
          dataj.ind1=2;                                   
        else                                              
          dataj.ind1=0;                                                                                             
      } /* if( -data.icon1[iprx] != jx ) */               

1
这相当于在一般情况下解决停机问题。 - n. m.
@n.1.8e9-我的份在哪里m。这不是停机问题,而是表达式等价性和数据类型问题。如果数据类型、分支和表达式映射相同,则算法相同。这是静态分析,而不是运行时分析。 - KJ7LNW
1个回答

1
这项任务似乎很难自动化。即使是经验丰富的程序员在试图找到这两个代码体之间语义上的有意义的差异时也会遇到极大的困难并感到头痛不已。
明显的区别是使用了fabs()fabsl(),即long double版本。但在表面下,需要跟踪所有使用的变量和函数的定义,最重要的是数据类型。变量具有相同的名称,但可能以微妙的不同类型定义,计算出不同的结果,通常非常接近,但有时非常不同。
编写一个C程序来执行对2个源文件的语义比较,忽略空格和注释是可行的,尽管不是易事。处理本地变量名称、函数名称、结构成员名称和布局的差异要困难得多,但可能可行。处理重构,例如将while循环改写为for循环,将测试转换为三元表达式,需要更多的工作,但并非不可能。但如果类型发生变化,则需要对值范围和精度进行全面分析,以确保语义一致,这似乎相当困难。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接