由于您正在调用未定义的行为,因此一个编译器崩溃而另一个编译器似乎可以工作是可以的。两者都是正确的——这就是未定义行为的美妙之处。
问题在于,jmp_buf
只要调用setjmp()
设置它的函数没有返回,保存的上下文 - the - 就保持有效。
C99 标准(不再是当前标准,但这种措辞不太可能发生重大变化)说:
§7.13.2.1longjmp
功能
该函数使用相应的参数在程序的同一调用中
longjmp
恢复最近一次调用宏所保存的环境。如果没有这样的调用,或者如果包含宏调用的函数在中间终止了执行( 208) ,或者如果宏的调用在具有可变修改类型的标识符的范围内并且执行已经离开该在此期间范围内,行为未定义。setjmp
jmp_buf
setjmp
setjmp
208)例如,通过执行return
语句或因为另一个longjmp
调用导致转移到setjmp
嵌套调用集中较早的函数中的调用。
您的代码几乎立即退出action_1()
,使jmp_buf
保存的内容setjmp()
一文不值。
几年前setjmp()
,我创建了这个小演示。longjmp()
它可能会帮助你。
/*
@(#)File: $RCSfile: setjmp.c,v $
@(#)Version: $Revision: 1.1 $
@(#)Last changed: $Date: 2009/10/01 16:41:04 $
@(#)Purpose: Demonstrate setjmp() and longjmp()
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2009
*/
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
static jmp_buf target_location;
static void do_something(void)
{
static int counter = 0;
if (++counter % 10 == 0)
printf("---- doing something: %3d\n", counter);
if (counter % 1000 == 0)
{
printf("||-- doing_something: calling longjmp() with value -1\n");
longjmp(target_location, -1);
}
}
static void do_something_else(int i, int j)
{
printf("-->> do_something_else: (%d,%d)\n", i, j);
do_something();
if (i > 2 && j > 2 && j % i == 2)
{
printf("||-- do_something_else: calling longjmp() with value %d\n", (i + j) % 100);
longjmp(target_location, (i + j) % 100);
}
printf("<<-- do_something_else: (%d,%d)\n", i, j);
}
static void doing_stuff(void)
{
int i;
printf("-->> doing_stuff()\n");
for (i = rand() % 15; i < 30; i++)
{
int j;
do_something();
for (j = rand() % 10; j < 20; j++)
{
do_something_else(i, j);
}
}
printf("<<-- doing_stuff()\n");
}
static void manage_setjmp(void)
{
printf("-->> manage_setjmp()\n");
switch (setjmp(target_location))
{
case 0:
/* Initial return - get on with doing stuff */
doing_stuff();
break;
case -1:
/* Error return - terminate */
printf("<<-- manage_setjmp() - error return from setjmp()\n");
return;
default:
/* NB: not officially possible to assign the return from setjmp() */
printf("---- manage_setjmp() - non-error return from setjmp()\n");
doing_stuff();
break;
}
printf("<<-- manage_setjmp()\n");
}
int main(void)
{
printf("-->> main()\n");
manage_setjmp();
printf("<<-- main()\n");
return(0);
}