C++ 检查跳转缓冲区是否有效(非本地跳转)
我们在代码库中实现了“longjmp–恢复堆栈环境”。C++ 检查跳转缓冲区是否有效(非本地跳转),c++,c,C++,C,我们在代码库中实现了“longjmp–恢复堆栈环境”。longjmp例程由特定的error\u exit函数调用,该函数可以从任何地方调用 因此,当调用longjmp时,可能未调用setjmp例程,并且缓冲区可能具有无效值,从而导致崩溃 我是否可以将缓冲区初始化为NULL,或者是否有任何检查可用于检查未设置或无效值。一种方法是,每当调用setjmp时,我都可以设置一个标志变量,我可以对此进行检查。但这只是一个小技巧 void error_exit() { extern jmp_buf b
longjmp
例程由特定的error\u 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 < /C>和jmp_buf
是不透明的,但后一个引用要求它是数组类型:
标题应定义数组类型jmp_buf
和<代码>sigjmp_buf
我相信在实践中,您将保存缓冲区,并在跳转到缓冲区之前将其与零进行比较,但在一些尚未发现的POSIX系统上,理论上允许使用全零的jmp_buf。如果您对此感到困扰(我不会),一个选项是将jmp
一个虚拟缓冲区设置到您从未使用过的某个跳转点,然后memcmp
您的jmp_buf
在跳转之前针对这个虚拟jmp_buf
。这样,您将只使用合法的(即由set_jmp
初始化)jmp_buf
s
另一种方法是维护一个单独的标志,指示它是否已初始化(或将两者包装在结构中)
我认为我应该在手册页reset_jmp
和long_jmp
上插入强制警告,因为它使应用程序难以读取,并且对信号处理有不可预测的影响(后者通过sigsetjmp()
治愈)。此外,在C++上下文中,它显然不会释放异常处理程序。 < P>代码> JMPUBUF>代码>没有特别详细说明。在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
离开函数后立即取消设置 我知道你想说什么,但是如果我使用一个虚拟缓冲区,代码不会跳到那里,有没有可能longjmp
优雅地不做任何事情,并且error\u exit
函数返回1longjmp
对统一化jmp\u buf
的影响是未定义的(或者更准确地说,根据标准“调用longjmp()
的效果,调用线程中未执行jmp_buf
结构的初始化是未定义的。”)因此,它可能不会做任何事情,但更有可能会做一些意外的事情(我的赌注是SEGV
或总线错误)事实上,C++中的乌布不是C++中的一个通过析构函数的龙JMP吗?就像一个旁注,<代码> LojMP(代码)>和朋友在C标准中定义(也可能在C++中)。.POSIX只遵循上面所说的。我真的很喜欢你的解决方案,我正在考虑试一试,有什么我需要知道的吗?你为什么删除malloc
?这不是更好吗?@Kartik Anand我已经把它推到了评论文本中。它更好,但并不等同于你原来的帖子。你需要关心freei在重新分配新值之前将其禁用。例如,if(buf!=NULL)free(buf);buf=malloc(sizeof(*buf));
或者更好的if(buf==NULL)buf=malloc(sizeof(*buf));
您需要小心,在使用相应的setjmp退出函数后不要使用longjmp(除非您正在破解一些共同例程,并且您确切地知道自己在做什么:)。