Найдите неиспользуемые структуры и элементы-структуры - PullRequest
5 голосов
/ 20 мая 2011

Некоторое время назад мы взяли на себя ответственность за унаследованную кодовую базу.

Одна из особенностей этого очень плохо структурированного / написанного кода заключалась в том, что он содержал ряд действительно огромных структур, каждая из которых содержала сотни членов. Одним из многих шагов, которые мы сделали, было очистить как можно больше кода, который не был использован, следовательно, необходимость найти неиспользуемые элементы структуры / структуры.

Что касается структур, я придумал комбинацию Python, GNU Глобальные и ctags для отображения списка неиспользуемых членов структуры.

По сути, я использую 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, использование компилятора - хороший способ сделать это. Я предпочитаю подход, который может выполнять своего рода фильтрацию высокого уровня перед использованием подхода компилятора.

Ответы [ 4 ]

1 голос
/ 25 июня 2014

Хотя это очень старый пост.Но недавно я сделал то же самое, используя python и gdb.Я скомпилировал следующий фрагмент кода со структурой в верхней части иерархии, а затем с помощью 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 голос
/ 20 мая 2011

Если это всего лишь несколько struct и если код не делает плохих попыток доступа к struct через другой тип ... тогда вы можете просто закомментировать все поля вашего первого struct и позволитькомпилятор скажет вам.

Раскомментируйте одно используемое поле за другим, пока компилятор не будет удовлетворен.Затем, как только это скомпилируется, к хорошему тестированию, чтобы гарантировать предварительное условие, что не было взломов.

Итерация по всем struct.

Определенно не красиво, но в конце у вас будетпо крайней мере, один человек, который немного знает код.

1 голос
/ 20 мая 2011

Использование покрытие . Это прекрасный инструмент для обнаружения недостатков кода, но он немного дорогой.

0 голосов
/ 20 мая 2011

В соответствии с правилами C, можно получить доступ к членам структуры через другую структуру, которая имеет похожую структуру. Это означает, что вы можете получить доступ к struct Foo {int a; float b; char c; }; через struct Bar { int x; float y; }; (за исключением, конечно, Foo::c).

Следовательно, ваш алгоритм потенциально ошибочен. Чертовски трудно найти то, что ты хочешь, кстати, поэтому С трудно оптимизировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...