- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试用 C 语言学习 setjump 和 longjump。任何人都可以帮助我了解以下代码的输出以及代码流和案例的解释。我在代码中调用了函数 funcall()。第一次迭代调用警报,但在后续迭代中未调用警报。为什么会这样? alarm(0) 是否会阻止任何 future 的警报请求?
编辑:即使删除了信号处理程序中的“print_T()”行,代码似乎也没有运行。
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <time.h>
#define LEN 50
jmp_buf po;
void print_T() {
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime ( &rawtime );
printf ( "Current local time and date: %s", asctime (timeinfo) );
}
static void ti() {
print_T();
longjmp(po,1);
}
int funcall(int reply) {
static int p;
p = 0;
signal(SIGALRM, ti);
int q = setjmp(po);
if(q == 0)
printf("the value BEFORE setjmp %d for reply %d\n", p, reply);
else
printf("the value AFTER setjmp %d for reply %d\n", p, reply);
alarm(5);
if(p > 0) {
printf("INVOKING THE ALARM");
alarm(0);
return -1;
}
p++;
for(int i = 0; i < 100000; i++)
for(int j = 0; j < 100000; j++);
return 0;
}
int main() {
int a;
int reply;
time_t start, end;
for(reply=0; ; reply++) {
printf("~~~~~~~~~~~~~~~~~~~~~~~~~ITERATION NUMBER %d\n", reply);
time(&start);
a = funcall(reply);
time(&end);
double tin = difftime(end, start);
printf("*********************ITERATION END and a returned is %d after %f\n", a, tin );
double tidiff = difftime(end, start);
if(a < 0)
if(reply == 10) {
break;
}
}
}
最佳答案
由于我的声誉低于 50,因此我无法对除我以外的任何帖子发表评论,以下是您的代码在 mac os 上执行时的输出:
我没有发现您的代码有任何问题 alarm(5)
被调用的次数与 funcall()
一样多被称为。
每次调用 funcall()
, 先拨alarm(5)
设置 SIGALRM 信号在 5 秒后传递给调用进程(它只是正在执行的函数/执行函数的线程),同时代码的其余部分执行。
自从每次调用 funcall()
静态变量 p 设置为 0,if(p > 0){...}
直到 p
才会执行 block 大于 0,只有当此 block 主体之后的下一条语句 p++
时才会发生递增 p
并使其大于零,被执行。
执行上述if block 并因此调用alarm(0)
取决于 for
所花费的时间循环关注 p++
终止。如果执行for
循环在 5 秒内完成,return 0
语句会将控制返回给调用函数。 return
将取消所有报警请求并销毁函数调用栈。所以,在这种情况下 alarm(0)
不被调用。
接下来,如果执行for
循环需要 > 5 秒(忽略所有可能发生的调度延迟,有时可能会导致意外行为),将触发未决警报,从而调用信号处理程序 ti()
.当信号处理程序 ti()
被调用,调用longjump()
在 setjump()
的调用指令处再次开始执行.当控制到达 alarm(0)
时(假设 for
循环一直执行,直到前面的 if
block 没有第二次执行),所有剩余的警报请求都被此调用取消。所以,alarm(0)
在 p>0 和 for
之后取消所有未决的警报请求循环时间超过 5 秒。
这里是通过asciinema记录的执行情况 https://asciinema.org/a/fyZX7CRoikq5kLJS2t0Og2rot
这是执行完成后 asciinema session 的屏幕截图。
关于c - 在c中设置跳转和跳远代码流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47304514/
我是一名优秀的程序员,十分优秀!