Page 330 - 《软件学报》2021年第7期
P. 330

2248                                     Journal of Software  软件学报 Vol.32, No.7,  July 2021

                    在共计达 519 万行的结果中,仅 37 735 行的统计次数达到 20 次及以上,仅 10 473 行统计次数达 50 次及以
                 上,而 100 次以上的行数仅有 4 679 行,可见在实际工程项目中频繁出现的行集中于极少一部分行内容上,这些
                 行往往是与代码中一些特殊语义结构相关的.因此,只要消除了这些常见行所带来的负面影响,即筛除这些常见
                 行而保留那些罕见且更能体现源代码功能特性的行,就能够解决大部分现存的误报,大幅度地提高算法可用性,
                 本文第 4 节的实验结果也证实了这一点.
                                              Table 1    Common lines in code files
                                                     表 1   常见重复行
                                            排序         行内容            出现次数
                                             1          }else{         74 960
                                             2          break;         48 733
                                             3        @Override        42 073
                                             4          break          29 730
                                             5          return;        24 601
                                             6           try{          22 353
                                             7        returnfalse;     21 238
                                             8          return         15 586

                    同时,可以注意到,如果将所有语言的代码文件一起进行常见行统计,其结果是不够合理的.这些影响结果
                 的常见行往往跟语言相关联,不同语言的常见行差异非常显著,因此不能采用统一的筛选器对所有语言的源代
                 码进行行筛选.对此,本文选取了 10 种常用语言(c#、c/c++、go、java、js、php、python、ruby、sql、swift),并
                 对每种语言分别进行常用行统计.数据源选自 Github 星数排名前 50 000 的开源项目,将其中每种语言的源代码
                 文件进行预处理后按出现频数降序排列,其中部分语言的常见行统计到前 15 名,结果见表 2.从表 2 可见,在代码
                 文件中频繁出现的行不仅包含纯符号行,也包含一些特殊的与语义相关的行,这些行在代码中的频繁出现并不
                 能直接地体现代码功能,包含的语义信息也较少,因此并不属于第 2.2 节中提到的频繁出现一些功能性行内容
                 的行覆盖情况.若仅通过纯符号行对结果进行筛选,其余频繁出现且特性体现较差的行就会影响指纹特征的提
                 取,比重较大时将出现行覆盖的情况,严重影响结果的精确度.同时,尽管不同语言之间有一些通用的常见行,如
                 “returnfalse;”“}else{”“return”等,但是由于不同语言的语法特点不同,其常见行列表之间差异性也较大,存在一些
                 语言特有的常见行,如 python 中的“pass”、ruby 中的“ensure”等.
                                         Table 2    Common code lines in different languages
                                                表 2   部分语言常见行统计结果
                          语言        行内容       语言     行内容      语言     行内容    语言        行内容
                                      }                }             else:             end
                                   @Override           {               )               else
                                      {              <?php            try:              }
                                    @test              );              }                )
                                     try{              ),             },              beforedo
                                    }else{             ],             pass             begin
                                    break;           }else{            ]                {
                          JAVA    returnfalse;  PHP   array(  python  ),     ruby       },
                                   returnthis;         ];            return           private
                                   returnnull;       break;         @property           ]
                                     });               [            continue      includeaws::structure
                                   returntrue;      returnfalse;      }),              super
                                    return;         return$this;    returnfalse         [
                                importjava.util.list;  ]              }],             ensure
                                     };                )             break        require'spec_helper'

                    如图 3 所示,左右两边的代码分别节选自不同工程的两个文件,从语义和功能的角度来看,两者截然不同.根
                 据现有的相似哈希计算方法,两个文件的每一行都将作为一个特征来共同计算指纹值,由于两边均多次出现
                 “#endif”行,导致最终计算出来的相似哈希指纹值的海明距离为 7.可以看到,两边多次出现的“#endif”行是对区
                 分完全没有帮助的,真正能够体现程序具体特性的是剩下的那些行.因此,与 TF-IDF 方法不同,本文提出的算法
   325   326   327   328   329   330   331   332   333   334   335