【问题标题】:Locate unused structures and structure-members定位未使用的结构和结构成员
【发布时间】:2011-08-29 14:49:24
【问题描述】:

不久前,我们接管了遗留代码库的责任。

这个非常糟糕的结构/编写代码的一个怪癖是 它包含许多非常大的结构,每个都包含 数百名成员。我们所做的众多步骤之一是清洁 尽可能多地删除未使用的代码,因此需要 查找未使用的结构/结构成员。

关于结构体,我想出了 python、GNU Globalctags 的组合来列出未使用的结构体成员。

基本上,我正在做的是使用ctags 来生成一个标签文件, 下面的 python 脚本解析该文件以找到所有结构 成员,然后使用GNU Global 在以前的 生成全局数据库以查看该成员是否在代码中使用。

这种方法有许多相当严重的缺陷,但它有点 解决了我们面临的问题,并为我们的进一步发展提供了良好的开端 清理。

一定有更好的方法来做到这一点!

问题是:如何找到未使用的结构和结构成员 在代码库中?

#!/usr/bin/env python

import os
import string
import sys
import operator

def printheader(word):
    """generate a nice header string"""
    print "\n%s\n%s" % (word, "-" * len(word))

class StructFreqAnalysis:
    """ add description"""
    def __init__(self):
        self.path2hfile=''
        self.name=''
        self.id=''
        self.members=[]

    def show(self):
        print 'path2hfile:',self.path2hfile
        print 'name:',self.name
        print 'members:',self.members
        print

    def sort(self):
        return sorted(self.members, key=operator.itemgetter(1))

    def prettyprint(self):
        '''display a sorted list'''
        print 'struct:',self.name
        print 'path:',self.path2hfile
        for i in self.sort():
            print '    ',i[0],':',i[1]
        print

f=open('tags','r')

x={} # struct_name -> class
y={} # internal tags id -> class

for i in f:
    i=i.strip()
    if 'typeref:struct:' in i:
        line=i.split()
        x[line[0]]=StructFreqAnalysis()
        x[line[0]].name=line[0]
        x[line[0]].path2hfile=line[1]
        for j in line:
            if 'typeref' in j:
                s=j.split(':')
                x[line[0]].id=s[-1]
                y[s[-1]]=x[line[0]]

f.seek(0)
for i in f:
    i=i.strip()
    if 'struct:' in i:
        items=i.split()
        name=items[0]
        id=items[-1].split(':')[-1]
        if id:
            if id in y:
                key=y[id]
                key.members.append([name,0])
f.close()

# do frequency count
for k,v in x.iteritems():
    for i in v.members:
        cmd='global -a -s %s'%i[0]     # -a absolute path. use global to give src-file for member
        g=os.popen(cmd)
        for gout in g:
            if '.c' in gout:
                gout=gout.strip()
                f=open(gout,'r')
                for line in f:
                    if '->'+i[0] in line or '.'+i[0] in line:
                        i[1]=i[1]+1
                f.close()

printheader('All structures')
for k,v in x.iteritems():
    v.prettyprint()

#show which structs that can be removed
printheader('These structs could perhaps be removed')
for k,v in x.iteritems():
    if len(v.members)==0:
        v.show()

printheader('Total number of probably unused members')
cnt=0
for k,v in x.iteritems():
    for i in v.members:
        if i[1]==0:
            cnt=cnt+1
print cnt

编辑

正如@Jens-Gustedt 所建议的,使用编译器是一个很好的方法。在使用编译器方法之前,我正在寻求一种可以进行“高级”过滤的方法。

【问题讨论】:

  • 您使用的是什么 IDE 和操作系统?
  • 在这种情况下是 Linux。没有IDE,我用vim。

标签: c linux gcc


【解决方案1】:

如果这些只是几个struct,并且如果代码没有通过另一种类型访问struct 的坏技巧......那么您可以注释掉您的第一个struct 的所有字段并让编译器告诉你。

取消注释一个又一个使用的字段,直到编译器满意为止。然后一旦编译,进行良好的测试以确保没有黑客攻击的前提。

遍历所有struct

绝对不漂亮,但最终你至少会有一个懂代码的人。

【讨论】:

  • 这是一种方法,但正如我所说,每个结构都有数百个成员,最大的一个有 250 多个成员。这种方法需要我一周的时间;-)
【解决方案2】:

使用coverity。这是检测代码缺陷的好工具,但成本有点高。

【讨论】:

  • 你知道我们应该在 Coverity 中使用哪些选项来检测结构中未使用的元素吗?是否也会与 UNUSED_VALUE 项一起报告?
【解决方案3】:

虽然这是一个非常古老的帖子。但最近我使用 python 和 gdb 做了同样的事情。我编译了以下 sn-p 代码,其结构位于层次结构的顶部,然后使用 gdb 在结构上打印类型并重新诅咒到其成员中。

#include <usedheader.h>
UsedStructureInTop *to_print = 0;
int main(){return 0;}

(gdb) p to_print
(gdb) $1 = (UsedStructureInTop *) 0x0
(gdb) pt UsedStructureInTop
type = struct StructureTag {
    members displayed here line by line
}
(gdb)

虽然我的目的有点不同。它是生成一个仅包含结构 UsedStructureInTop 及其依赖类型的标头。有编译器选项可以做到这一点。但它们不会删除在包含的头文件中找到的未使用/未链接的结构。

【讨论】:

  • 有趣,今晚我会看看这个。同时为努力+1 :-)
【解决方案4】:

在 C 规则下,可以通过具有类似布局的另一个结构访问结构成员。这意味着您可以通过struct Bar { int x; float y; }; 访问struct Foo {int a; float b; char c; };(当然Foo::c 除外)。

因此,您的算法可能存在缺陷。很难找到你想要的东西,顺便说一句,这就是 C 语言难以优化的原因。

【讨论】:

  • 我的算法有很大缺陷,要求所有成员变量都有唯一的名称!这就是为什么我要问...
猜你喜欢
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多