将C代码更改为完全运行(包括if的所有部分)

将C代码更改为完全运行(包括if的所有部分),c,performance,testing,automation,dead-code,C,Performance,Testing,Automation,Dead Code,注:我意识到我的问题不清楚。我现在已经修改过了,首先为我犯的错误道歉 我有一个很大的C项目,它将在嵌入式系统上运行。我使用ARM编译器。 代码分布在多个子文件夹中,由.c和.h文件组成 我想计算一下什么函数被调用了多少次,这样我就可以识别死代码,并加速最常用的函数。ARM编译器有几个选项用于删除无法访问的代码,当函数指针起作用时,它会失败 因此,我希望遍历代码的每个分支,并记录对函数的调用次数 例如(这是一个非常简单的程序,用于演示我要查找的内容,而不是原始代码): 我希望遍历整个代码,以便访问

注:我意识到我的问题不清楚。我现在已经修改过了,首先为我犯的错误道歉

我有一个很大的C项目,它将在嵌入式系统上运行。我使用ARM编译器。 代码分布在多个子文件夹中,由.c和.h文件组成

我想计算一下什么函数被调用了多少次,这样我就可以识别死代码,并加速最常用的函数。ARM编译器有几个选项用于删除无法访问的代码,当函数指针起作用时,它会失败 因此,我希望遍历代码的每个分支,并记录对函数的调用次数

例如(这是一个非常简单的程序,用于演示我要查找的内容,而不是原始代码):

我希望遍历整个代码,以便访问if分支的所有部分(即foo1、foo2和foo3)。这将帮助我确定哪个函数被调用了多少次。 在上面的示例中,调用foo1()的频率比调用foo2()的频率高,而从未调用foo4()。 因此,识别和删除foo4()并优化foo1()是有意义的

有什么想法/工具来运行整个代码吗

我认为其中一种方法是修改主函数,如下所示:

int main (void)
{
    int x ;

    x = rand (11);

    //*************************************************
    //starting modification
    int a = 1; //added by me
    if_1: //added by me
    if (a == 1)
    {
        foo1(); //original code
        foo2(); //original code

        a=2; //added by me
        goto if_1; //added by me
    }

    else if (a==2)
    {
        foo2(); //original code
        a=3; //added by me
        goto if_1: //added by me
    }
    else             foo3(); //original code
    //end of modification
    //********************************************************        

    return 0;
}
这样它就可以运行原始代码。
知道如何进行这种修改吗?

您也可以用这种方式更改
main()
函数

int main (void)
{
    int x = 5;
    while () {
       if (x==5)        { foo1(); x=10;}
       else if (x==10)  { foo2(); x=0; }
       else             { foo3(); break;}
    }
    return 0;
}

基本上,您需要的是所谓的评测(每个函数调用多少次)和代码覆盖率(遍历代码的每个分支)。如果您使用的是
gcc
,您应该查看用于分析的
-p
选项和用于代码覆盖的
--coverage
选项。这两个选项都向程序添加代码,以便在运行程序时进行测量。然后使用程序
gprof
查看分析结果,使用程序
gcov
查看代码覆盖率

我不完全明白你为什么要改变原来的计划。上述方法依赖于精心构造的程序测试输入,以提供具有代表性的执行(用于分析)和高代码覆盖率。在您的示例程序中,编译器可能会优化掉对
foo2
foo3
的调用,因为没有可能触发这些调用的程序输入。相反,如果您的程序看起来像:

#include <stdio.h>

void foo1(void)
{
    printf("Value is 5");
}

void foo2(void)
{
    printf("Number is 10");
}

void foo3(void)
{
    printf("Number is neither 10 nor 5");
}

int main (int argc, char ** argv)
{
    switch (argc)
    {
    case 5: foo1(); break;
    case 10: foo2(); break;
    default: foo3(); break;
    }

    return 0;
}
#包括
void foo1(void)
{
printf(“值为5”);
}
无效2(无效)
{
printf(“数字为10”);
}
void foo3(void)
{
printf(“数字既不是10也不是5”);
}
int main(int argc,字符**argv)
{
开关(argc)
{
案例5:foo1();中断;
案例10:foo2();中断;
默认值:foo3();break;
}
返回0;
}
然后以
a.out 1
a.out 1 2 3 4
a.out 1 2 3 4 5 6 7 8 9
的形式运行该程序将使程序通过所有分支。这三次运行将全面覆盖该计划

应该注意的是,分析和代码覆盖本身就是一门艺术。在生成测试集以获得高代码覆盖率方面已经做了很多研究,但是我认为没有广泛使用的工具来生成这样的测试集。主要是因为这不是小事。然而,手动生成代码覆盖率高的测试集是软件测试中的标准步骤。

intmain(void)
int main (void)
{
    int x = 5;
#ifdef DEBUG
    int debug_i, debug_data[] = { 5, 10, 20 };
    for(debug_i = 0;debug_i<sizeof debug_data / sizeof *debug_data;++debug_i){
        x = debug_data[debug_i];
#endif
    if (x==5)        foo1();
    else if (x==10)  foo2();
    else             foo3();
#ifdef DEBUG
    }
#endif

    return 0;
}
{ int x=5; #ifdef调试 int debug_i,debug_data[]={5,10,20};
对于(debug_i=0;debug__i=0)您不能只删除if并写入
a=1;foo1();a=2;foo2();a=3;foo3();
?为什么不使用探查器或其他检测工具?既然您强制每个函数调用一次,那么“确定调用了多少次哪个函数”是什么意思?我仍然不确定您想要实现什么。跟踪哪个函数被调用的频率有什么帮助?您想要“自动化”什么?@bennofs:函数没有访问a的权限,那么a是否存在又有什么关系呢?我认为返回应该在循环之后。好的,你能告诉我如何自动更改主函数吗?很抱歉没有把原来的问题弄清楚。添加了更多的细节和解释。我在处理嵌入式系统的同时,也在处理ARM编译器系统。关于如何为ARM执行上述操作,您有什么想法吗?很抱歉没有将原始问题解释清楚。添加了更多详细信息和解释。@user1928721通过这些更改,我认为我的答案更合适。您实际上是在看分析和代码覆盖率。如果您确实有一个随机生成器,您可能希望替换它这是一个列举所有相关值的方法,以获得一些决定论。为没有使原始问题足够清楚而道歉。添加了更多细节和解释。
int main (void)
{
    int x = 5;
#ifdef DEBUG
    int debug_i, debug_data[] = { 5, 10, 20 };
    for(debug_i = 0;debug_i<sizeof debug_data / sizeof *debug_data;++debug_i){
        x = debug_data[debug_i];
#endif
    if (x==5)        foo1();
    else if (x==10)  foo2();
    else             foo3();
#ifdef DEBUG
    }
#endif

    return 0;
}