在Linux/GCC下将NULL指针访问转换为C++异常

use*_*983 5 c++ linux gcc exception stack-unwinding

有没有办法将NULL指针访问转换为Linux下的C++异常?类似于Java中的NullPointerException.我希望以下程序能够成功返回,而不是崩溃(假设编译器在编译期间无法找出此NULL指针访问):

class NullPointerException {};

void accessNullPointer(char* ptr) {
    *ptr = 0;
}

int main() {
    try {
        accessNullPointer(0);
    } catch (NullPointerException&) {
        return 1;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我不期望任何标准的方法,因为C++下的NULL指针访问是未定义的 - 行为,只是想知道如何在x86_64 Linux/GCC下完成它.

我做了一些非常原始的研究,有可能:

  1. 当在Linux下访问NULL指针时,将生成SIGSEGV.
  2. 在SIGSEGV处理程序内部,程序的内存和寄存器信息将可用(如果sigaction()用于注册信号处理程序).如果程序被反汇编,也可以使用导致SIGSEGV的指令.
  3. 修改程序的内存和/或注册,并创建/伪造异常实例(可能通过调用低级展开库函数,如_Unwind_RaiseException等)
  4. 最后从信号处理程序返回,希望程序启动一个C++堆栈展开过程就像抛出正常异常一样.

以下是GCC手册页的引用(-fnon-call-exceptions):

生成允许捕获指令以抛出异常的代码.请注意,这需要在任何地方都不存在的特定于平台的运行时支持.此外,它只允许捕获指令抛出异常,即内存引用或浮点指令.它不允许从诸如"SIGALRM"之类的任意信号处理程序抛出异常.

看来这个"特定于平台的运行时"正是我想要的.任何人都知道这样的Linux/x86_64运行时?或者如果没有这样的运行时已经存在,请给我一些关于如何实现这样的运行时的信息?

我希望该解决方案也适用于多线程程序.

Pet*_*ker 2

不,没有什么好办法可以做到这一点,也不应该有。异常是由源代码中的语句引发的throw。这对于推理异常安全性非常重要:您可以查看代码并查看可以引发异常的位置,也许更重要的是,您可以查看代码并查看不会引发异常的位置。如果您所做的几乎任何事情都可能引发异常,那么编写异常安全的代码而不用catch子句弄乱它就变得非常困难。微软在他们早期的 C++ 编译器中尝试过这一点:他们在操作系统的结构化异常之上搭载了 C++ 异常处理,结果是一场灾难。