在c中设置跳转和跳远代码流
set jump and long jump codeflow in c
我正在尝试学习 C 中的 setjump 和 longjump。任何人都可以帮助我输出以下代码以及代码流和 cases.i 调用函数 funcall() 的解释在代码中。第一次迭代调用警报,但在后续迭代中未调用警报。为什么会这样? alarm(0) 是否会阻止任何未来的警报请求?
编辑:即使删除了信号处理程序中的 "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,因此我不能对除我以外的任何 post 发表评论,这里是您的代码在 mac [=66= 上执行时的输出]:
我没有发现您的代码有任何问题,因为 alarm(5)
的调用次数与 funcall()
的调用次数一样多。
每次调用 funcall()
,第一次调用 alarm(5)
设置 SIGALRM 信号传递给调用进程(它只不过是函数正在 executed/thread 执行函数)在 5 秒后执行代码的其余部分。
因为在每次调用funcall()
静态变量时p被设置为0,if(p > 0){...}
块将不会被执行直到p
大于 0,仅当执行此块主体之后的下一条语句 p++
递增 p
并使其大于零时才会发生。
前面提到的 if 块的执行和因此对 alarm(0)
的调用取决于 p++
之后的 for
循环所花费的时间终止。如果 for
循环的执行在 5 秒内完成,return 0
语句将 return 控制权交给调用函数。 return
将取消所有报警请求并销毁函数调用堆栈。因此,在这种情况下 alarm(0)
不会被调用。
接下来,如果 for
循环的执行时间 > 5 秒(忽略所有可能发生的调度延迟,有时可能会导致意外行为),将触发未决警报,从而调用信号处理程序 ti()
。当调用信号处理程序 ti()
时,将调用 longjump()
并在 setjump()
的调用指令处再次开始执行。当控制到达 alarm(0)
时(假设 for
循环持续执行,只要前面的 if
块没有第二次执行),所有剩余的警报请求都被取消通过这个电话。因此,alarm(0)
在 p>0 和 for
循环时间超过 5 秒后取消所有未决警报请求。
这里是通过asciinema记录的执行
https://asciinema.org/a/fyZX7CRoikq5kLJS2t0Og2rot
这是执行完成后 asciinema 会话的屏幕截图。
我正在尝试学习 C 中的 setjump 和 longjump。任何人都可以帮助我输出以下代码以及代码流和 cases.i 调用函数 funcall() 的解释在代码中。第一次迭代调用警报,但在后续迭代中未调用警报。为什么会这样? alarm(0) 是否会阻止任何未来的警报请求?
编辑:即使删除了信号处理程序中的 "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,因此我不能对除我以外的任何 post 发表评论,这里是您的代码在 mac [=66= 上执行时的输出]:
我没有发现您的代码有任何问题,因为 alarm(5)
的调用次数与 funcall()
的调用次数一样多。
每次调用 funcall()
,第一次调用 alarm(5)
设置 SIGALRM 信号传递给调用进程(它只不过是函数正在 executed/thread 执行函数)在 5 秒后执行代码的其余部分。
因为在每次调用funcall()
静态变量时p被设置为0,if(p > 0){...}
块将不会被执行直到p
大于 0,仅当执行此块主体之后的下一条语句 p++
递增 p
并使其大于零时才会发生。
前面提到的 if 块的执行和因此对 alarm(0)
的调用取决于 p++
之后的 for
循环所花费的时间终止。如果 for
循环的执行在 5 秒内完成,return 0
语句将 return 控制权交给调用函数。 return
将取消所有报警请求并销毁函数调用堆栈。因此,在这种情况下 alarm(0)
不会被调用。
接下来,如果 for
循环的执行时间 > 5 秒(忽略所有可能发生的调度延迟,有时可能会导致意外行为),将触发未决警报,从而调用信号处理程序 ti()
。当调用信号处理程序 ti()
时,将调用 longjump()
并在 setjump()
的调用指令处再次开始执行。当控制到达 alarm(0)
时(假设 for
循环持续执行,只要前面的 if
块没有第二次执行),所有剩余的警报请求都被取消通过这个电话。因此,alarm(0)
在 p>0 和 for
循环时间超过 5 秒后取消所有未决警报请求。
这里是通过asciinema记录的执行 https://asciinema.org/a/fyZX7CRoikq5kLJS2t0Og2rot
这是执行完成后 asciinema 会话的屏幕截图。