c++ - 如何在 C++ 中防止/抑制 SIGFPE?

标签 c++

我正在尝试将 double 转换为 float 以及 dll 中的各种整数类型,用作 Game Maker 扩展。如果 double 不符合目标类型的范围,我不需要合理的结果,所以我只是使用了 static_cast。

当我从我自己的测试 C++ 应用程序调用此代码时,一切都按预期工作,但当它从 Game Maker 调用时,范围错误出于某种原因引发 SIGFPE,这导致 Game Maker 终止我的程序并显示一条错误消息。

对于超出范围的转换,我不需要合理的结果,但崩溃是不行的。我尝试使用 llround 而不是强制转换,但它也会发出信号。

我还尝试使用 signal(SIGFPE, SIG_IGN) 自己捕捉信号;就在转换之前,但它根本没有改变行为。也许 mingw signal.h 中的不祥评论与此有关:“SIGFPE 似乎不起作用?”

我检查了 Game Maker 扩展中使用的不同 dll 的源代码,作者提供的二进制文件执行简单的转换没有问题。但是,当我自己编译源代码时,SIGFPE 问题再次出现。我猜作者使用了不同的编译器,但如果可能的话我更愿意继续使用 mingw。

那么,我该如何安全地执行这些转换,或者在我使用简单的强制转换执行这些转换时防止生成信号?我目前正在使用 mingw-g++ 4.5.0 进行编译。

这是发生问题的函数:

template<typename ValueType>
static double writeIntValue(double handle, double value) {
    boost::shared_ptr<Writable> writable = handles.find<Writable>(handle);
    if(writable) {
        // Execution reaches this point
        ValueType converted = static_cast<ValueType>(value);
        // Execution doesn't reach this point if e.g. ValueType 
        // is short and value is 40000
        writable->write(reinterpret_cast<uint8_t *>(&converted), sizeof(converted));
    }
    return 0;
}

最佳答案

好的解决方案是通过在转换之前确保源值在目标类型的范围内来正确执行转换。所以我的问题代码可以这样更正:

ValueType converted;
if(value >= std::numeric_limits<ValueType>::max()) {
    converted = std::numeric_limits<ValueType>::max();
} else if(value <= std::numeric_limits<ValueType>::min()) {
    converted = std::numeric_limits<ValueType>::min();
} else {
    converted = static_cast<ValueType>(value);
}

另一种选择是使用 Boost 库中的 numeric_cast,如果源值超出范围,它会抛出异常,因此它为所有转换定义了行为。

Boost 数值转换库的文档包含一些 helpful information关于标准如何定义某些转化。

感谢 rve 在他的回答中提供了正确的建议,但不幸的是他的示例代码有缺陷,我想添加一些额外的帮助我的指针。

关于c++ - 如何在 C++ 中防止/抑制 SIGFPE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4690545/

相关文章:

c++ - boost::multi_index 是否仍在积极维护?

C++11 正确的结构初始化

c++ - 为什么在循环外提升字符串会导致性能下降?

c++ - valgrind 无法识别无效写入

c++ - 处理自定义异常的类

c++ - 执行结束时出现段错误(核心转储)

c++ - Z3:在 z3::expr 上使用比较运算符 (<,<=,...)

c++ - 将波形文件读入带符号的 float 组

c++ - 动态内存分配是如何工作的

c++ - 为什么我的图书馆管理程序没有写入文件