Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将SIGFPE转换为C++异常_C++_Linux_Exception_Signals - Fatal编程技术网

如何将SIGFPE转换为C++异常

如何将SIGFPE转换为C++异常,c++,linux,exception,signals,C++,Linux,Exception,Signals,在Win32下,使用_set_se_translator很容易将SEH异常转换为C++异常。在Linux上是否有类似的方法将某些信号转换为C++异常?我需要一个SIGFPE到C++异常的映射。在POSIX系统(如Linux)上无法可靠地实现这一点。有关更多详细信息,请参见。请注意,您不能在您的案例中使用。我假设您使用的是x86-64上的Linux或其他一些常用的体系结构 请特别仔细阅读有关信号处理程序中异步信号安全函数的内容,它们是处理SIGFLE等信号的唯一方法。还请阅读C++11标准或C99

在Win32下,使用_set_se_translator很容易将SEH异常转换为C++异常。在Linux上是否有类似的方法将某些信号转换为C++异常?我需要一个SIGFPE到C++异常的映射。

在POSIX系统(如Linux)上无法可靠地实现这一点。有关更多详细信息,请参见。请注意,您不能在您的案例中使用。我假设您使用的是x86-64上的Linux或其他一些常用的体系结构

请特别仔细阅读有关信号处理程序中异步信号安全函数的内容,它们是处理SIGFLE等信号的唯一方法。还请阅读C++11标准或C99标准对信号的说明。大多数C++实现有时会生成一些对运行时支持函数的隐式调用,这些函数不是异步信号安全的,尤其是那些抛出异常的函数。因此,您无法可靠地从信号处理程序引发异常

实际上,以下情况可能是错误的信号处理程序:

你可以通过用G++WALL-O-FVBUSE ASM -S编译它,然后查看发射的S汇编文件,它调用C++运行时中的一些非异步信号安全函数,如……xCasaLoLaTeaTyExo,yxCxaPaLoad,yununr.Read禁止……< /P> 在实践中,对于不中止或不退出的信号处理程序,唯一安全的方法是设置一些易失性的SIGAMATIC标志,或使用一些异步信号安全函数,例如,在一个。另外,从信号处理程序抛出异常并不比从它调用printf更糟糕,因为很多人都做得不好;这是被禁止的,但它经常会起作用。我仍然不建议这样做,特别是在运行时间很长的程序中,或者在崩溃(甚至不经常)是不可接受的情况下

阅读更多关于,尤其是Lattner的博客

在实践中,处理信号的唯一可靠和可移植的方法是使用一个只设置一些易失性信号标志的信号处理程序。但是如果您对SIGFPE执行此操作,那么您的实现很可能会在相同的状态下重新启动相同的计算,从而在SIGFPE处理上无限期地循环。同样,我认为这可能并不总是正确和可靠的;事实上,未定义的行为似乎经常起作用


实际上,我强烈怀疑Windows的转换方式不是C++ 11或C++ 14标准或C99或C11标准一致,并且可以在Windows上有一个标准的一致实现C++或C99或C11,这是不允许的,你建议做什么;很可能Clang或GCC就是这样的实现。

使用g++,您可以使用-fnon-call-exceptions选项,只需从FPE信号处理程序抛出一个异常即可。注意,并非每个信号都可以这样映射,只有捕获指令产生的信号。幸运的是,SIGFPE就是这样一个信号。

也许你应该编辑你的问题来改进和激励它,特别是解释你为什么要这样做,以及你真正考虑的SIGFPE的确切情况。@Basile Starynkevitch对于每一个经验最少的软件工程师来说,这样做的动机应该是显而易见的!一种更好、通常更快、当然更便于携带的做法是避免整数除以零或使用IEEE双精度。看一个相关的答案,然后阅读,当然,你确定它总是可靠地工作吗?例如,在某个析构函数(可能是一个exception@BasileStarynkevitch这就像从析构函数中抛出一样。你为什么要在析构函数中使用浮点呢?我的感觉是,这种方法会产生未定义的行为,而这些行为通常可能会起作用。@BasileStrynkevich当然这是符合标准的,但gcc定义了当你这样做时会发生什么。它是一个扩展,says about-fnon-call异常生成代码,允许捕获指令抛出异常。请注意,这需要特定于平台的运行时支持,而这种支持并非无处不在。此外,它只允许捕获指令抛出异常,即内存引用或浮点指令。它不允许从任意信号处理程序(如SIGALRM)抛出异常。。我不像你那样理解。禁止从sigbal处理程序调用某些函数适用于用C编写的用户代码。这并不意味着实现本身不能调用此类函数,也不意味着它不能保证POSIX列表中没有的其他函数的安全。理论上你可能是对的,但实际上你是错的,在x86-64上,SIGFPE可以被一个整数零除调用,这个整数零除可以发生在任何地方,包括在实现标准容器的代码中,因为它们的未定义行为,当然也可以发生在机器代码任意点的用户代码中。您不能责怪-fnon-call异常由于不恰当导致无法从UB恢复
与标准容器相关的te代码。它不能向你保证这一点。至于用户代码,-fnon-call异常的要点是使其在存在陷阱(包括FPE陷阱)引起的异常时表现良好。我不在乎编译器是怎么做到的。如果您认为文档没有承诺这一点,请针对文档提交一个bug。它让人相信这样的承诺是存在的。根据您的解释,您仍然没有说明文档承诺了什么。如果它承诺了什么,说什么;如果它没有任何承诺,可能会提交一个关于无用开关的bug。
/// WRONG CODE, against signal(7) since calling 
/// non-async-signal-safe functions from the C++ runtime
void badSIGFPEhandler(int sig) {
  if (sig == SIGFPE)
    throw std::runtime_error("got SIGFPE");
}