我目前正在用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处理,不应该发生。
答案 0 :(得分:2)
如果永远不会从异步信号不安全代码调用信号处理程序,那么从信号处理程序调用{{1}}是安全的。因此,例如,如果您可能通过将错误指针传递给任何longjmp()
系列函数来接收SIGSEGV,则不能从信号处理程序printf()
中获取。{/ p>
答案 1 :(得分:1)
我可以依靠现代destkop操作系统上的signal.h
您可以依赖它,因为标题及其中的函数将在所有符合标准的系统上可用。但是,究竟是什么信号被抛出以及何时在操作系统之间不一致。
在Windows上,您可能需要使用cygwin或类似环境编译程序,以使系统引发分段错误。使用visual studio编译的程序使用“structured exceptions”来处理无效的存储访问。
signal.h是一种捕获空指针的可靠方法吗?
即使在POSIX系统上,也存在空指针取消引用不会导致引发分段错误信号的情况。
然后是你的信号处理程序的实现。 longjmp
不是异步信号安全,因此如果在执行另一个非安全操作时引发了信号,则中断的操作可能使程序处于不一致状态。有关详细信息,请参阅John Zwinck的answer和libc documentation。