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

C++ signal.h是捕获空指针的可靠方法吗?,c++,c,error-handling,operating-system,signals,C++,C,Error Handling,Operating System,Signals,我目前正在用C/C++编写一个小型虚拟机。显然,如果用户取消引用空指针,我不能让整个虚拟机崩溃,因此我必须检查每个访问,随着虚拟机的增长和更多系统的实现,访问变得越来越麻烦 因此,我有了一个想法:为sigsegv编写一个信号处理程序,让操作系统完成它的工作,但不要关闭程序,而是调用VM异常处理程序 它似乎可以工作(在我非常简单的测试用例中),但我没有发现任何东西可以保证在null derefs上抛出Sigsegv,也没有找到任何可以为操作系统生成的信号调用处理程序的东西 所以我的问题是: 我能指

我目前正在用C/C++编写一个小型虚拟机。显然,如果用户取消引用空指针,我不能让整个虚拟机崩溃,因此我必须检查每个访问,随着虚拟机的增长和更多系统的实现,访问变得越来越麻烦

因此,我有了一个想法:为sigsegv编写一个信号处理程序,让操作系统完成它的工作,但不要关闭程序,而是调用VM异常处理程序

它似乎可以工作(在我非常简单的测试用例中),但我没有发现任何东西可以保证在null derefs上抛出Sigsegv,也没有找到任何可以为操作系统生成的信号调用处理程序的东西

所以我的问题是: 我能指望现代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处理,不应该发生。

从信号处理程序调用
longjmp()
只有在从未从异步信号不安全代码调用信号处理程序时才是安全的。因此,例如,如果您可能通过传递指向任何
printf()
函数族的错误指针来接收SIGSEGV,则无法从信号处理程序中获取
longjmp()

我能指望现代destkop操作系统上的signal.h吗

您可以信赖它,因为所有符合标准的系统都可以使用标头和其中的函数。然而,抛出什么信号以及何时抛出,在操作系统中并不一致

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


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

有些情况下,即使在POSIX系统上,空指针解引用也不会导致引发分段故障信号

  • 一种情况可能是编译器优化了操作,这是典型的情况,例如,取消引用空指针以调用不访问任何数据成员的成员函数。当没有无效内存访问时,也没有信号。当然,在这种情况下也不会发生撞车
  • 另一种情况可能是地址0实际上是有效的。AIX上就是这种情况,您不关心它。Linux上也是如此,您确实关心它,但不是默认情况,您可能会选择不关心它所在的位置。有关更多详细信息,请参阅


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

除了取消引用空指针外,代码还可以取消引用垃圾指针或任何其他类型的无效指针。这不一定会产生信号。因此,除了验证每个指针访问之外,您别无选择。如果您将指针取消引用操作传递给主机操作系统,则它不是VM。充其量它是一个模拟包装器(尽管不要告诉WINE它就是这样!)@Sam Varshavchik:这就是为什么最后一个音符出现的原因:垃圾不应该发生:永远。@OP:不,但您担心的似乎是处理一般的分段错误,而不仅仅是空指针。例如:
*(int*)(-5)=1
可能会生成SEGFULT,即使它不包含任何空指针。我了解到处理程序函数不应返回(因为它具有undef行为)。这是否意味着我必须手动清理对printf的呼叫?C++的IO也是这样吗?它不仅仅是Prtf,它是任何未在这里明确列出的标准库函数:是的,它包括C++ I/O,它是用C函数实现的,而且它包含了比I/O更多的信息(对于另一个例子, MKTimes)(< /代码>不能使用)。非常感谢,先生。这就是我要找的!