0

我即将与我们的团队一起使用 C 语言为在线活动编写一个死代码删除算法。

要求是......

  1. 读取一个 C 程序源文件,其中有多种形式的死代码。
  2. 我们的输出应该是一个文件,它没有任何死代码。

在上网时,我们遇到了 SO 链接......

我如何知道代码中的哪些部分从未使用过?

遗留 C/C++ 项目中的死代码检测

在看到这些链接之前,我们有一个基本的想法......使用普通文件流逐行读取输入 C 文件并存储在字符串数组中。然后分析这些字符串并确定非常基本的死代码,如 if(0) 和 if(1) 等。并制作一个堆栈,以维护括号。还有更多...

但这有一个很大的问题,这个想法将导致我们更多地使用字符串操作而不是删除死代码。

但是在看到这些链接之后......我们开始了解 Clang 库、抽象语法树、控制流图等......

但我们对这些库和那些概念非常陌生。我们知道它们是用来解析 C 代码的。

因此,我们需要一些关于这些 AST、CFG 的基本概念和一些基本指导,解释我们如何在代码中使用它们......

我们可以将那个 clang 库包含为像 math.h 这样的普通库吗?

我们在哪里可以下载那个库?

我们可以在 Windows 中使用那些 Clang 库吗?

4

2 回答 2

4

我可以向您解释控制流图的概念,但我对库本身并不熟悉。

这个概念很简单。将任何连续的代码行(即没有ifgoto或函数调用或标签)想象为图的一个节点。每个goto或函数调用都会创建从当前节点到goto标签所在节点或它正在调用的函数的定向链接。请记住,函数本身可以是图而不是简单的节点,因为它if内部可能有 s 或其他函数调用。每个函数调用还创建从函数的叶节点(函数returns 所在的位置)到函数调用后包含代码的节点的定向链接。(这可以创建很多从函数图传出的链接,因为该函数可以在代码的许多部分中调用)

同样,如果您有,则从当前节点到语句的部分和部分if都有两个方向链接(除非您检测到或像您说的那样,在这种情况下只有一个链接到正确的位置)ifelseifif(0)if(1)

图的根是 的入口点main。现在,要找到死代码,您必须做的是简单地从根位置遍历图(例如使用 DFS 或 BFS),最后查看哪些节点未被访问。这向您显示了死代码,即代码中的位置,无论您的程序采用什么方向,它都不会到达这些位置。

如果你想自己实现这个,你可以采取递归的方法(类似于解析代码但更简单)。例如,如果你看到一个if你说:

typedef char *line;
FlowGraph *get_flow_graph(line *code)
{
    FlowGraph *current_node = malloc(sizeof *current_node);
    current_node->flow_to = malloc(some_maximum * sizeof *current_node->flow_to);
    current_node->flow_to_count = 0;
    ...
    if (is_if_statement(code[0]))
    {
        FlowGraph *if_part = get_flow_graph(code + 1);
        FlowGraph *else_part = get_flow_graph(code + find_matching_else(code));
        current_node->flow_to[current_node->flow_to_count++] = if_part;
        current_node->flow_to[current_node->flow_to_count++] = else_part;
    }
    else
    ...
}
于 2011-08-26T15:08:23.153 回答
0

您可以看到由DMS 软件再造工具包提取的控制和数据流图示例。

我们已经使用 DMS 的数据流分析机制及其C 前端在非常大的应用程序(2600 万行 C)上完成了这项工作,包括点到点分析,如果您真的想在大型应用程序中找到死函数,这是实际需要的C系统。

于 2011-08-26T16:51:16.763 回答