[英]Check if jump buffer is valid or not (non-local jumps)
我们在代码库中实现了“longjmp-Restore堆栈环境”。 longjmp
例程由特定的error_exit
函数调用,该函数可以从任何地方调用。
因此,当调用longjmp
时,可能没有调用setjmp
例程,并且缓冲区可能具有导致崩溃的无效值。
我可以将缓冲区初始化为NULL
还是可以检查是否有未设置或无效的值。 一种方法是每当调用setjmp
时我都可以设置一个标志变量,我可以检查它。 但那只是一个黑客。
void error_exit()
{
extern jmp_buf buf;
longjmp(buf, 1);
return 1;
}
我可以这样做吗?
void error_exit()
{
extern jmp_buf buf;
if(buf)
longjmp(buf, 1);
return 1;
}
代码是混合的C / C ++,我知道我可以在任何地方用C ++异常处理替换setjmp
和longjmp
,但现在这是不可能的,我可以用无效缓冲区捕获longjmp
导致崩溃吗?
jmp_buf
没有特别好记录。 在linux标题中,你可以找到类似的东西:
typedef int __jmp_buf[6];
struct __jmp_buf_tag {
__jmp_buf __jmpbuf; /* Calling environment. */
int __mask_was_saved; /* Saved the signal mask? */
__sigset_t __saved_mask; /* Saved signal mask. */
};
typedef struct __jmp_buf_tag jmp_buf[1];
将其设置为零然后测试整个大小可能会浪费时间。
就个人而言,我会保留一个指向此缓冲区的指针,将其初始化为NULL并在setjmp之前设置它。
jmp_buf physical_buf;
jmp_buf *buf = NULL;
...
buf = &physical_buf;
if (setjmp(*buf)) {
...
}
这与拥有单独的旗帜的想法相同。 此外,您可以根据需要动态分配jmp缓冲区。
知道缓冲区是否已设置并不是一个真正的问题,您可以只拥有一个包含该信息的辅助变量。
真正的问题是你不能longjmp
横行,这是有不确定的行为,并且由于根本原因无法工作。 从您调用setjmp
的函数返回后,该函数的堆栈将被无效并被后续调用覆盖。 所以setjmp
上下文不再有效。 我不是在谈论jmp_buf
本身,而是谈论它中记录的堆栈状态。
所以你唯一能做的就是有一个辅助变量来记录你是否已经设置了缓冲区,并且一旦你将函数与setjmp
放在一起就会解除设置。
好问题。
据我所知,从POSIX标准( http://pubs.opengroup.org/onlinepubs/9699919799/functions/longjmp.html http://pubs.opengroup.org/onlinepubs/9699919799/functions/setjmp.html http ://pubs.opengroup.org/onlinepubs/9699919799/basedefs/setjmp.h.html ) jmp_buf
是不透明的,除了后一个引用要求它是一个数组类型:
<setjmp.h>
头文件应定义数组类型jmp_buf
和...sigjmp_buf
。
我相信在实践中你会保存bzero()
缓冲区,并在跳转到它之前将它与零进行比较,但理论上,在一些尚待发现的POSIX系统中,所有零jmp_buf
都是允许的。 如果你(我不会)打扰这一点,一个选择是set_jmp
虚拟缓冲区你永远不会使用一些跳跃点,然后memcmp
你jmp_buf
反对这种假jmp_buf
做前跳。 这样你只能使用合法的(即由set_jmp
初始化) jmp_buf
。
另一种方法是维护一个单独的标志,指示它是否已经初始化(或者在struct
包装)。
我相信我应该在manpage re set_jmp
和long_jmp
上插入强制警告,因为它使应用程序难以阅读,并且对信号处理有不可预测的影响(后者用sigsetjmp()
)。 此外,在C ++上下文中,它显然不会展开您的异常处理程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.