当我在无限循环中使用 gettimeofday() 时程序意外停止

Program stops unexpectedly when I use gettimeofday() in an infinite loop

我写了一段代码来确保 while(1) 循环的每个循环都花费特定的时间(在这个例子中是 10000µS,等于 0.01 秒)。问题是这段代码在开始时运行良好,但不知何故不到一分钟后就停止了。好像有访问linux的时间限制。现在,我正在初始化一个布尔变量以使这次计算 运行 一次而不是无限。由于性能随时间变化,因此最好计算每个循环的计算时间。有没有其他方法可以做到这一点?

void some_function(){
struct timeval tstart,tend;
while (1){
   gettimeofday (&tstart, NULL);
   ...
   Some computation
   ...
   gettimeofday (&tend, NULL);
   diff = (tend.tv_sec - tstart.tv_sec)*1000000L+(tend.tv_usec - tstart.tv_usec);
   usleep(10000-diff);
   }
}

from man-page of usleep

 #include <unistd.h>

 int usleep(useconds_t usec);

usec 是 unsigned int,现在猜猜下行中 diff > 10000 时会发生什么

 usleep(10000-diff);

好吧,你计算差值是错误的:

diff = (tend.tv_sec - tstart.tv_sec)*1000000L+(tend.tv_usec - tstart.tv_usec);

您正在混合不同的整数类型,缺少 tv_usec 可以是一个 unsigned 数量,您正在从另一个 unsigned 中减去它并且可以溢出....之后,结果是整整一秒加上大约 4.0E09usec 的数量。这是大约 4000 秒。或一个多小时.... aproximately。最好检查是否有一些进位,在这种情况下,增加 tv_sec,然后从 tv_usec 中减去 10000000 以获得适当的正值。

我不知道您为 struct timeval 使用的实现,但最有可能的是 tv_sectime_t(甚至可以是 64 位),而 tv_usec 通常只是一个 unsigned 32 位值,因为它不会比 1000000.

更远

让我举例说明...假设您已经用了 100 毫秒进行计算...而这恰好发生在一秒钟的中间...您有

tstart.tv_sec = 123456789; tstart.tv_usec = 123456;
tend.tv_sec = 123456789; tend.tv_usec = 223456;  

当你减去时,它会导致:

tv_sec = 0; tv_usec = 100000;

但假设您在第二次更改时完成了计算

tstart.tv_sec = 123456789; tstart.tv_usec = 923456;
tend.tv_sec =  123456790; tend.tv_usec = 23456;

时差又是 100 毫秒,但是现在,当您计算表达式时,第一部分得到 1000000(一整秒),但是减去第二部分后得到 23456 - 923456 =*=> 4294067296 (* ) 溢出。 所以你可以达到 usleep(4295067296)4295s.1h 11m 更多。 我认为您没有足够的耐心等待它完成...但这可能会发生在您的程序中,具体取决于 struct timeval 的定义方式。

使进位起作用的正确方法是重新排序求和以先进行所有加法,然后再进行减法。这在一起处理 signedunsigned 时强制强制转换为有符号整数,并防止 unsigneds.

中的负溢出
diff = (tend.tv_sec - tstart.tv_sec) * 1000000 + tstart.tv_usec - tend.tv_usec;

解析为

diff = (((tend.tv_sec - tstart.tv_sec) * 1000000) + tstart.tv_usec) - tend.tv_usec;