什么是AST、CFG、CLANG,我们如何在死码删除算法中使用它?

什么是AST、CFG、CLANG,我们如何在死码删除算法中使用它?,c,parsing,clang,abstract-syntax-tree,dead-code,C,Parsing,Clang,Abstract Syntax Tree,Dead Code,我准备用C语言为我们团队的一个在线活动编写一个死代码删除算法 这些要求是 读取一个C程序源文件,其中有许多形式的死代码 我们的输出应该是一个没有死代码的文件 在网上冲浪的时候,我们遇到了这么多的链接 在看到这些链接之前,我们有了基本的想法。。。 使用普通文件流逐行读取输入C文件,并存储在字符串数组中。 然后分析这些字符串并确定非常基本的死代码,如if(0)和if(1)等。。 以及制作一个堆栈,用于维护括号。还有更多 但这有一个很大的问题,这个想法将引导我们更多地使用字符串操作,而不是删除死代

我准备用C语言为我们团队的一个在线活动编写一个死代码删除算法

这些要求是

  • 读取一个C程序源文件,其中有许多形式的死代码
  • 我们的输出应该是一个没有死代码的文件
  • 在网上冲浪的时候,我们遇到了这么多的链接

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

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

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

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

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

    我们可以把那个叮当作响的库作为一个普通的库,比如math.h吗

    我们在哪里可以下载那个图书馆


    我们可以在windows中使用那些铿锵的库吗?

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

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

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

    图形的根是
    main
    的入口点。现在,要找到死代码,您必须做的是从根位置(例如使用DFS或BFS)简单地遍历图,最后查看哪些节点没有被访问。这会显示死掉的代码,也就是说,无论程序朝哪个方向运行,它都不会到达这些位置

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

    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
        ...
    }
    

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

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

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

    图形的根是
    main
    的入口点。现在,要找到死代码,您必须做的是从根位置(例如使用DFS或BFS)简单地遍历图,最后查看哪些节点没有被访问。这会显示死掉的代码,也就是说,无论程序朝哪个方向运行,它都不会到达这些位置

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

    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
        ...
    }
    
    您可以看到由提取的图的示例

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

    您可以看到由


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

    只是为了得到这个想法:尝试使用以下链(假设你已经安装了llvm和clang二进制文件)
    clang-cc1yourfile.c;opt-O3-globaldce-dce yourfile.bc-o optfile.bc;llc-march=c optfile.bc
    。什么样的“在线活动”建议把它作为没有经验的人的任务?。。