2016-06-11 100 views
0

我有一个C应用程序,其中的一个工作是调用一个可执行文件。该文件在编译期间在中间代码级别插入了性能测量例程。它可以测量时间或L1/L2/L3缓存未命中。换句话说,我修改了LLVM编译器以插入对该函数的调用,并将结果打印到stdout以获得任何已编译的程序。如何在C程序运行时正确调用可执行文件?

现在,就像我在开始时提到的那样,我想从单独的C应用程序执行程序(该结果返回到stdout)并保存该结果。我这样做是正确的,现在的方式是:

void executeProgram(const char* filename, char* time) { 
    printf("Executing selected program %s...\n", filename); 
    char filePath[100] = "/home/michal/thesis/Drafts/output/"; 
    strcat(filePath, filename); 
    FILE *fp; 
    fp = popen(filePath, "r"); 
    char str[30]; 
    if (fp == NULL) { 
     printf("Failed to run command\n"); 
     exit(1); 
    } 
    while (fgets(str, sizeof(str) - 1, fp) != NULL) { 
     strcat(time, str); 
    } 
    pclose(fp); 
} 

其中filename是名称的编译的可执行文件运行。结果保存为time字符串。

问题是,我得到的结果与通过从命令行(./test16)手动运行可执行文件返回的结果相比,是非常不同和不稳定的。它们看起来像:

231425 
229958 
230450 
228534 
230033 
230566 
231059 
232016 
230733 
236017 
213179 
90515 
229775 
213351 
229316 
231642 
230875 

因此,他们大多在23万美国,有一些偶然的下降。同样的可执行文件,从其他应用程序中运行,生产:

97097 
88706 
91418 
97970 
97972 
94597 
95846 
95139 
91070 
95918 
107006 
89988 
90882 
91986 
90997 
88824 
129136 
94976 
102191 
94400 
95215 
95061 
92115 
96319 
114091 
95230 
114500 
95533 
102294 
108473 
105730 

注意,它是相同的可执行文件,被呼叫。然而,它返回的测量时间是不同的。正在测量的程序包括对简单嵌套循环的函数调用,访问数组元素。下面是代码:

#include "test.h" 
#include <stdio.h> 

float data[1000][1000] = {0}; 


void test(void) 
{ 
    int i0, i1; 
    int N = 80; 
    float mean[1000]; 
    for (i0 = 0; i0 < N; i0++) 
    { 
     mean[i0] = 0.0; 
     for (i1 = 0; i1 < N; i1++) { 
      mean[i0] += data[i0][i1]; 
     } 
     mean[i0] /= 1000; 
    } 
} 

我怀疑有,也许过程中应分叉一些错误的程序代码调用的方式还是什么?有任何想法吗?

+0

哦,对不起,我已经把时间单位弄糊涂了,实际上时间只有几微秒。好吧,我会尽力解释它。 –

+0

当您从“其他应用程序”执行时,您是否使用循环调用多次?像'for(i = 0; i <20; ++ i)executeProgram(...)' – 4386427

+0

我不这样做,它只运行一次 –

回答

0

你没有指定你的时间测量子程序的插入位置,所以我所能提供的只是猜测。

结果似乎暗示了完全相反 - 从shell运行应用程序比较慢,所以我不担心从C代码启动进程的方式。我的猜测是 - 当你从shell运行你的程序时,终端会让你放慢速度。当你从你的C代码运行这个过程时,你将输出传送回你的'starter'应用程序,它已经在等待管道上的输入。

请注意,从strcat切换到更安全的方式,如strncat

+0

如果您计算了“strcat”函数的长度,预先串好。但是,在OP案中,他没有。 'strncat'没有任何安全性,因为它会导致无声的未终止字符串,而不是(通常是崩溃)溢出。 – fuz

+0

@FUZxxl如果未检查输入中的错误,则会导致应用程序崩溃,是的。什么'strncat'更好地防止缓冲区溢出代码执行类型的攻击(在这个例子中并不是真的,但在处理'foreign'字符串时记住这一点非常重要)。 – Kelm

+0

如果您检查长度,那么'strcat'和'strncat'同样安全。 – fuz

相关问题