C++ 检查跳转缓冲区是否有效(非本地跳转)

C++ 检查跳转缓冲区是否有效(非本地跳转),c++,c,C++,C,我们在代码库中实现了“longjmp–恢复堆栈环境”。longjmp例程由特定的error\u exit函数调用,该函数可以从任何地方调用 因此,当调用longjmp时,可能未调用setjmp例程,并且缓冲区可能具有无效值,从而导致崩溃 我是否可以将缓冲区初始化为NULL,或者是否有任何检查可用于检查未设置或无效值。一种方法是,每当调用setjmp时,我都可以设置一个标志变量,我可以对此进行检查。但这只是一个小技巧 void error_exit() { extern jmp_buf b

我们在代码库中实现了“longjmp–恢复堆栈环境”。
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>和 LojJMP < /Cord>,但是现在不可能,我能用无效的缓冲来捕获<代码> LojJMP < /C> >,导致崩溃?

< P>好问题。 从POSIX标准来看()
jmp_buf
是不透明的,但后一个引用要求它是数组类型:

标题应定义数组类型
jmp_buf
和<代码>sigjmp_buf

我相信在实践中,您将保存缓冲区,并在跳转到缓冲区之前将其与零进行比较,但在一些尚未发现的POSIX系统上,理论上允许使用全零的jmp_buf。如果您对此感到困扰(我不会),一个选项是
将jmp
一个虚拟缓冲区设置到您从未使用过的某个跳转点,然后
memcmp
您的
jmp_buf
在跳转之前针对这个虚拟
jmp_buf
。这样,您将只使用合法的(即由
set_jmp
初始化)
jmp_buf
s

另一种方法是维护一个单独的标志,指示它是否已初始化(或将两者包装在
结构中)


我认为我应该在手册页re
set_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
函数返回1
longjmp
对统一化
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(除非您正在破解一些共同例程,并且您确切地知道自己在做什么:)。