2012-09-25 40 views
1

编译器在函数范围内检测未使用的变量。但是,我发现在结构中定义了许多变量,这些变量从不读取(但可能已经写了很多次)。是否有任何工具/分析器或甚至编译器标志来检测这些未使用的变量?检测函数范围之外的未使用变量

示例: 例如,在以下结构:

typedef struct jj_t { 
    int count; 
    int *list; 
} jj; 

分析器可能会发现count永远不会在代码的任何地方读取。

我对我的代码的分析显示这经常发生!这是我的错,但这可能是多年来由不同用户开发的应用程序的常见情况。删除这些变量可能会显着减少内存使用量。我只需要一个工具来检测这些变量,我会手动删除它们。

在此先感谢。

+4

[这里是一个列表](http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#C.2FC.2B.2B)用于C和C++的静态分析工具。他们中的一些人可能能够检测到你的情况。 –

+0

哦,我有很多这些。不能被打扰修复它们。与DID需要修复的其他大规模开发工作相比,除非嵌入式代码具有有限的内存(这种情况下,我将消除所有未使用的内存位),否则这对于我来说是一个微不足道的问题。 –

回答

1

我可以给一个解决方案。

但是:

  1. 的努力可能比人工检测大得多。几乎所有适合程序员的IDE都允许您查看给定变量的所有引用。

  2. 这可能不适用于任何情况,您需要专门针对某些类型。

  3. 这将通过单个程序运行收集。

这个想法是包装你的数据类型。通过这种封装,您可以计算每个读取操作。 请参阅:

template <class T, class Parent, int NO=1> 
class TReadDetector { 
public: 
    struct Data { 
     bool touched; 
     Data() : touched(false) {} 
     ~Data() { 
     if (!touched) 
      std::cerr << typeid(*this).name() << ": not read!!!\n" << std::endl; 
     } 
    }; 
    static Data data; 
    TReadDetector() {} 
    TReadDetector (const T& t) : t(t) {} 
    operator T() const { data.touched = true; return t; } 
    TReadDetector& operator = (const T& t) { this->t = t; } 
private: 
    T t; 
}; 

template <class T, class Parent, int NO> 
typename TReadDetector<T,Parent,NO>::Data 
         TReadDetector<T,Parent,NO>::data; 

与用法:

相反的:

struct A { 
    int a; 
    int b; 
}; 

做到这一点:

struct A { 
    TReadDetector<int,A, 1> a; 
    TReadDetector<int,A, 2> b; 
}; 


int main() { 
    A a; 
    a.a = 7; 
    a.b = 8; 
    std::cout << a.a << std::endl; 
    std::cout << TReadDetector<int,A, 1>::data.touched << std::endl; 
    std::cout << TReadDetector<int,A, 2>::data.touched << std::endl; 
    std::cout << "main() ended" << std::endl; 
}; 

它将导致:

7 
1 
0 
main() ended 
N13TReadDetectorIi1ALi2EE4DataE: not read!!! 

通知最后一行main()后打印。您可以将这些数据收集到一些外部文件。

+0

好包装!我有一个链接列表数据结构,我使用malloc()分配一个节点,释放()释放它。我认为这就是为什么这个包装没有检测到未使用的变量(注意:我手动找到了未使用的变量)。使用malloc/free时,我看起来不会调用解构器!我对吗? – ahmad

+0

静态元素的d-tor应该被调用 - 就像你在我的例子中可以看到的那样:即使我将'A a;'改变为'A * a = new A;',它也可以工作。没有看到这个打印输出的原因可能是不同的 - 也许在'main()'之后,所有打印输出都被丢弃。无论如何 - 这不是真正的解决方案 - 只是一个想法,表明跟踪所有变量的读数是可能的。 – PiotrNycz

1

任何分析都必须跨越翻译单位。

实际上,与您不同,我从未发现这是一个问题。关于 我能想到的唯一解决方案就是删除 之一的成员,并查看整个应用程序是否仍在编译。

+0

使用__attribute __((不建议使用))会比删除少一点激进;-) – stefan

+1

OP:“(但可能已经写了很多次)”? – PiotrNycz

+0

如果变量没有读取不写,请确定。但是,没有阅读很多写道呢!! – ahmad

-1

从结构中除去本场可在少数情况下,危险的,如果我们使用的结构是怎样的,

typedef struct jj_t {  int count;  int *list; } jj; 

jj *ptr = malloc (...); 

//.... 

*ptr = 5; // NAIVE (but I have seen usage like this). 
      // Actually you are not modifying count, count was already deleted. 

所以,很难做到你要求的分析。

+1

-1。所提供的代码是不可编译的,因为除了这个相同类型的另一个结构之外,你不能分配给一个结构,但是你想给它赋一个整数(5)。此外,这不能回答这个问题。这可以很好的评论。 –