我有完整的 C 项目,可以用 gcc 或 Visual Studio 构建。没有调用外部库。
我想知道该项目中有多少功能。
源代码中没有未使用的函数,并且该项目附带了使用不同参数运行它的测试,因此对于动态方法(例如运行时调用树),我需要在每次测试后累积结果。
有没有可以进行静态或动态分析的工具?
我有完整的 C 项目,可以用 gcc 或 Visual Studio 构建。没有调用外部库。
我想知道该项目中有多少功能。
源代码中没有未使用的函数,并且该项目附带了使用不同参数运行它的测试,因此对于动态方法(例如运行时调用树),我需要在每次测试后累积结果。
有没有可以进行静态或动态分析的工具?
与gcc
:
$ nm elf_file | grep "T " | grep -v " _" | wc -l
请注意, gcc
即使禁用优化也可以内联某些函数,因此您应该编译:
-O0 -fno-builtin -fno-inline-functions-called-once
(-finline-functions-called-once
即使在 中也默认启用-O0
)
函数的定义可能不像你想象的那么简单。特别是,C 源代码中的函数与生成的汇编代码中的函数不匹配,这主要是因为内联函数。
函数的数量和大小取决于优化级别和编译器。
许多标头(例如<stdio.h>
)可能包含内联函数。如果不调用它们,编译器可能会通过不发出它们的代码来优化(对于某些静态函数也是如此)。很多时候,声明的函数static inline
不会出现在优化的代码中。
同样,一些宏可能会扩展为一些函数定义......
如果使用足够新的 GCC 版本(例如 4.7 或更高版本)进行编译,您可能会为此目的制作一个简单的MELT扩展。最大的优点是它可以在 GCC 内部工作,因此会真正计算 GCC 正在做什么……(例如,经过一些优化)。
请注意,GCC 可能会在优化期间生成或删除一些函数(函数克隆、函数内联....)
GCC MELT 自 2017 年起已过时
Frama-C有一个metrics
插件,除其他外,它可以计算程序中的函数数量。只需使用
frama-c -metrics file1.c file2.c ... filen.c
得到如下输出:
Global metrics
==============
Sloc = 2080
Decision point = 117
Global variables = 51
If = 117
Loop = 22
Goto = 75
Assignment = 613
Exit point = 242
Function = 841
Function call = 871
Pointer dereferencing = 447
您还可以使用 ctags 并解析标记文件。一种快速的方法是执行以下操作:
ctags -R -f - . | grep -w f | wc -l
在项目的根目录中,但这可能并不总是正确的,例如,如果您在树的某处有这样的全局变量:
int f;
Edison Design Group 是一个对 C 源代码进行静态分析的工具。它是编译器前端,您可以利用它来计算代码的各种指标。
我有一个想法来计算函数 .c 文件。我们也可以计算这个 .java 文件。这是 c# 类文件,您可以将文件传递给类
class CountFunctions
{
private FileInfo File;
private int functions = 0;
public int getNumberOfFunctions
{
get { return functions; }
}
public countfunctions(FileInfo fs) {
File = fs;
getLineOfCode();
}
private void getLineOfCode()
{
string line;
try
{
StreamReader reader = File1.OpenText();
while (true)
{
line = reader.ReadLine();
if (IsFunction(line))
{
Functions++;
}
if (line == null)
break;
}
}
catch (Exception r)
{
Console.WriteLine(r.Message);
}
}
private bool IsFunction(string line)
{
if (line.Contains("void") || line.Contains("int") || line.Contains("short") || line.Contains("long") || line.Contains("float") || line.Contains("char") || line.Contains("double"))
{
if (!line.Contains(";"))
{
return true;
}
}
return false;
}
}