Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在c中设置跳跃和跳远码流_C_Setjmp - Fatal编程技术网

在c中设置跳跃和跳远码流

在c中设置跳跃和跳远码流,c,setjmp,C,Setjmp,我正在尝试学习C语言中的setjump和longjump。有谁能帮助我输出以下代码以及代码流和案例解释。我在代码中调用了函数funcall()。在第一次迭代中调用报警,但在随后的迭代中不调用报警。为什么会这样?报警(0)是否阻止任何未来的报警请求 编辑:即使删除信号处理程序中的“print_T()”行,代码似乎也不会运行 #include <stdio.h> #include <setjmp.h> #include <signal.h> #include &l

我正在尝试学习C语言中的setjump和longjump。有谁能帮助我输出以下代码以及代码流和案例解释。我在代码中调用了函数funcall()。在第一次迭代中调用报警,但在随后的迭代中不调用报警。为什么会这样?报警(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;
           }

    }

}
#包括
#包括
#包括
#包括
#定义LEN 50
jmp_buf po;
无效打印(){
时间与时间;
结构tm*时间信息;
时间(&rawtime);
timeinfo=localtime(&rawtime);
printf(“当前本地时间和日期:%s”,asctime(timeinfo));
}
静态孔隙ti(){
print_T();
longjmp(po,1);
}
int funcall(int回复){
静态int-p;
p=0;
信号(SIGALRM,ti);
int q=setjmp(po);
如果(q==0)
printf(“设置jmp%d之前的值,用于回复%d\n”,p,reply);
其他的
printf(“setjmp%d之后的值,用于回复%d\n”,p,reply);
警报(5);
如果(p>0){
printf(“调用警报”);
报警(0);
返回-1;
}
p++;
对于(int i=0;i<100000;i++)
对于(int j=0;j<100000;j++);
返回0;
}
int main(){
INTA;
int回复;
开始、结束的时间;
for(reply=0;reply++){
printf(“~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~迭代编号%d\n”,答复);
时间(&开始);
a=funcall(回复);
时间(&结束);
双锡=扩散时间(结束、开始);
printf(“*********************迭代结束,返回的是%f\n”后的%d”,a,tin);
双TIDIF=difftime(结束,开始);
if(a<0)
if(回复==10){
打破
}
}
}

由于我的声誉不到50,因此除了我的帖子之外,我无法对其他帖子发表评论,因此,以下是在mac os上执行代码时的输出:

我认为您的代码没有任何问题,因为调用
报警(5)
的次数与调用
funcall()
的次数相同

对于每次调用
funcall()
,第一次调用
alarm(5)
将设置SIGALRM信号,该信号将在5秒后发送到调用进程(这只是正在执行的函数/线程执行该函数),而代码的其余部分将执行

由于在对
funcall()
静态变量p的每次调用中设置为0,
if(p>0){…}
块将不会执行,直到
p
大于0,只有当该块体后面的下一条语句
p++
递增
p
并使其大于0时才会执行该块,被执行

上述if块的执行,因此调用
报警(0)
取决于
循环在
p++
之后终止所用的时间。如果
for
循环的执行在5秒内完成,
return 0
语句将把控件返回给调用函数。
返回将取消所有报警请求并销毁函数调用堆栈。因此,在这种情况下,不会调用
报警(0)

接下来,如果执行
for
循环需要>5秒(忽略所有可能发生并有时可能导致意外行为的调度延迟),将触发挂起的警报,从而调用信号处理程序
ti()
。当调用信号处理程序
ti()
时,将调用
longjump()
,并在
setjump()
的调用指令处再次开始执行。当控件到达
报警(0)
时(假设
for
循环的
持续执行时间与前面的
相同,如果第二次未执行
块),则此调用将取消所有剩余的报警请求。因此,
alarm(0)
会在p>0之后取消所有挂起的报警请求,而
for
循环所需时间超过5秒

以下是通过asciinema记录的执行情况

下面是执行完成后asciinema会话的屏幕截图


我建议您先阅读,例如。您所做的可能是个坏主意。@有些程序员在这里有很多“坏主意”,比如从信号处理程序调用非异步安全函数。@EOF请详细说明。这是我第一次使用setjmp和longjmpApart,因为它们的想法不好,在ubuntu16.04linux
intq=setjmp(po)上似乎确实“起作用”
您不能从setjump分配(甚至更糟:将其用作初始值设定项表达式)“返回值”,您只能对其进行测试。