signal.h是一种捕获空指针的可靠方法吗?

时间:2016-07-10 12:29:02

标签: c++ c error-handling operating-system signals

我目前正在用C / C ++编写一个小型VM。显然,如果用户取消引用空指针,我不能让整个虚拟机崩溃,所以我必须检查随着虚拟机的发展和实施更多系统而变得繁琐的每次访问。

所以我有一个想法:为sigsegv写一个信号处理程序并让操作系统做它的事情,但不是关闭程序调用VM异常处理程序。

它似乎工作(使用我非常简单的测试用例),但我没有找到任何保证Sigsegv被抛出null-derefs,也没有找到处理器生成的信号处理程序。

所以我的问题是: 我可以依靠现代destkop操作系统上的signal.h(我真的不在乎它是不是标准的不适用于linux / win以外的东西:它是一个宠物项目)。是否有任何非常重要的事情我应该注意(信号(...)或longjmp(...)的模糊限制?)

谢谢!

这是伪实现:

/* ... */

jmp_buf env;

/* ... */

void handler(int) {
    longjmp(env, VM_NULLPTR);
}

/* ... */

if(setjmp(env)) {
    return vm_throw("NullPtrException");
} 
switch(opcode) {

    /* instructions */

    case INVOKE:
        *stack_top = vm_call(stack_top->obj); // don't check anything in the case where stack_top or stack_top->obj is null handler() will be called an a "NullPtrException" will be thrown
    break;

    /* more instructions */

}

/* ... */

注意:我只需要检查空值,垃圾(悬空)指针由GC处理,不应该发生。

2 个答案:

答案 0 :(得分:2)

如果永远不会从异步信号不安全代码调用信号处理程序,那么从信号处理程序调用{​​{1}}是安全的。因此,例如,如果您可能通过将错误指针传递给任何longjmp()系列函数来接收SIGSEGV,则不能从信号处理程序printf()中获取。{/ p>

答案 1 :(得分:1)

  

我可以依靠现代destkop操作系统上的signal.h

您可以依赖它,因为标题及其中的函数将在所有符合标准的系统上可用。但是,究竟是什么信号被抛出以及何时在操作系统之间不一致。

在Windows上,您可能需要使用cygwin或类似环境编译程序,以使系统引发分段错误。使用visual studio编译的程序使用“structured exceptions”来处理无效的存储访问。

  

signal.h是一种捕获空指针的可靠方法吗?

即使在POSIX系统上,也存在空指针取消引用不会导致引发分段错误信号的情况。

  • 一种情况可能是编译器已经优化了操作,这通常是例如在解除引用空指针以调用不访问任何数据成员的成员函数的情况下。当没有无效的存储器访问时,也没有信号。当然,在这种情况下也不会发生崩溃。
  • 另一种情况可能是地址0实际上是有效的。在AIX上就是这种情况,你不关心它。在Linux上也是如此,你确实关心它,但默认情况下不是这样,你可能会选择不关心它的情况。有关详细信息,请参阅this answer

然后是你的信号处理程序的实现。 longjmp不是异步信号安全,因此如果在执行另一个非安全操作时引发了信号,则中断的操作可能使程序处于不一致状态。有关详细信息,请参阅John Zwinck的answerlibc documentation