[英]Check if jump buffer is valid or not (non-local jumps)
We have implemented "longjmp–Restore stack environment" in our code base. 我们在代码库中实现了“longjmp-Restore堆栈环境”。 The
longjmp
routine is called by a particular error_exit
function which can be invoked from anywhere. longjmp
例程由特定的error_exit
函数调用,该函数可以从任何地方调用。
Thus it is possible that when longjmp
is called the setjmp
routine may not have been called and the buffer can have invalid value leading to a crash. 因此,当调用
longjmp
时,可能没有调用setjmp
例程,并且缓冲区可能具有导致崩溃的无效值。
Can I initialise the buffer to NULL
or is there any check available to check for unset or invalid value. 我可以将缓冲区初始化为
NULL
还是可以检查是否有未设置或无效的值。 One way is that I can set a flag variable whenever setjmp
is called, and I can check against that. 一种方法是每当调用
setjmp
时我都可以设置一个标志变量,我可以检查它。 But that is only a hack. 但那只是一个黑客。
void error_exit()
{
extern jmp_buf buf;
longjmp(buf, 1);
return 1;
}
Can I do something like this? 我可以这样做吗?
void error_exit()
{
extern jmp_buf buf;
if(buf)
longjmp(buf, 1);
return 1;
}
The code is mixed C/C++, I know I can replace setjmp
and longjmp
with C++ exception handling everywhere, but that is not possible now, can I instead catch longjmp
with invalid buffer which leads to a crash? 代码是混合的C / C ++,我知道我可以在任何地方用C ++异常处理替换
setjmp
和longjmp
,但现在这是不可能的,我可以用无效缓冲区捕获longjmp
导致崩溃吗?
jmp_buf
is not particularly well documented. jmp_buf
没有特别好记录。 In linux headers, you can find something like: 在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];
Setting it to zero and then test whole size may be a lost of time. 将其设置为零然后测试整个大小可能会浪费时间。
Personally, I would keep a pointer to this buffer, initializing it to NULL and setting it right before setjmp. 就个人而言,我会保留一个指向此缓冲区的指针,将其初始化为NULL并在setjmp之前设置它。
jmp_buf physical_buf;
jmp_buf *buf = NULL;
...
buf = &physical_buf;
if (setjmp(*buf)) {
...
}
It is the same idea as having a separate flag. 这与拥有单独的旗帜的想法相同。 Moreover you can allocate jmp buffers dynamically if necessary.
此外,您可以根据需要动态分配jmp缓冲区。
Knowing whether the buffer has been set or not is not a real problem, you could just have an auxiliary variable that holds that information. 知道缓冲区是否已设置并不是一个真正的问题,您可以只拥有一个包含该信息的辅助变量。
The real problem is that you can't longjmp
sideways, this is has undefined behavior and can't work for fundamental reasons. 真正的问题是你不能
longjmp
横行,这是有不确定的行为,并且由于根本原因无法工作。 Once you returned from the function in which you have called setjmp
the stack of that function is invalidated and overwritten by subsequent calls. 从您调用
setjmp
的函数返回后,该函数的堆栈将被无效并被后续调用覆盖。 So the setjmp
context isn't valid anymore. 所以
setjmp
上下文不再有效。 And I am not talking of the jmp_buf
itself, but of the stack state that is recorded in it. 我不是在谈论
jmp_buf
本身,而是谈论它中记录的堆栈状态。
So the only thing you can do is to have an auxiliary variable that records if you have set the buffer, and that you unset as soon that you leave the function with the setjmp
in question. 所以你唯一能做的就是有一个辅助变量来记录你是否已经设置了缓冲区,并且一旦你将函数与
setjmp
放在一起就会解除设置。
Good question. 好问题。
As far as I can see from the POSIX standard ( 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
is opaque, save that the latter reference requires it to be an array type: 据我所知,从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
是不透明的,除了后一个引用要求它是一个数组类型:
The
<setjmp.h>
header shall define the array typesjmp_buf
and ...sigjmp_buf
.<setjmp.h>
头文件应定义数组类型jmp_buf
和...sigjmp_buf
。
I believe in practice you would be save bzero()
-ing the buffer, and comparing it against zero before jumping to it, but in theory an all zero jmp_buf
would be permissible on some as yet to be discovered POSIX system. 我相信在实践中你会保存
bzero()
缓冲区,并在跳转到它之前将它与零进行比较,但理论上,在一些尚待发现的POSIX系统中,所有零jmp_buf
都是允许的。 If you were bothered about this (I wouldn't be), an option would be to set_jmp
a dummy buffer to some jump point you never use, and then memcmp
your jmp_buf
against this dummy jmp_buf
before doing the jump. 如果你(我不会)打扰这一点,一个选择是
set_jmp
虚拟缓冲区你永远不会使用一些跳跃点,然后memcmp
你jmp_buf
反对这种假jmp_buf
做前跳。 That way you would only use legal (ie initialized by set_jmp
) jmp_buf
s. 这样你只能使用合法的(即由
set_jmp
初始化) jmp_buf
。
An alternative would be to maintain a separate flag indicating whether it has been initialised (or wrap both in a struct
). 另一种方法是维护一个单独的标志,指示它是否已经初始化(或者在
struct
包装)。
I believe I should insert the mandatory warning on the manpage re set_jmp
and long_jmp
, in that it makes applications difficult to read, and has unpredictable effects on signal handling (the latter cured with sigsetjmp()
). 我相信我应该在manpage re
set_jmp
和long_jmp
上插入强制警告,因为它使应用程序难以阅读,并且对信号处理有不可预测的影响(后者用sigsetjmp()
)。 Also, in a C++ context it obviously does not unwind your exception handlers. 此外,在C ++上下文中,它显然不会展开您的异常处理程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.