首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C++中防止/抑制SIGFPE?

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

Stack Overflow用户
提问于 2011-01-14 19:27:51
回答 3查看 1.2K关注 0票数 0

我正在尝试在dll中将双精度类型转换为浮点数以及各种整数类型,该dll用作Game Maker扩展。如果double不适合目标类型的范围,我就不需要一个合理的结果,所以我简单地使用了static_cast。

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

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

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

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

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

下面是出现问题的函数:

代码语言:javascript
复制
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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-18 00:09:57

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

代码语言:javascript
复制
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在他的答案中提供了正确的建议,但不幸的是,他的示例代码有缺陷,我想添加一些额外的指针来帮助我。

票数 1
EN

Stack Overflow用户

发布于 2011-01-14 23:34:39

由于您使用的是DLL,您确定该DLL的编译方式与程序预期的方式相同吗?可能是32/64位不匹配?

此外,当转换时存在欠/上溢时,也可以引发SIGFPE。

您可以通过使用_FPU_SETCW (它在fpu_control.h中)设置掩码来启用/禁用此溢出所引发的信号。我猜是Game Maker启用了此功能,而您的测试程序不启用此功能。

我从来没有尝试过,我不确定mingw也有这个功能,但我希望这会有一点帮助。

编辑:

为什么不确保不发生溢出呢?

类似于:

代码语言:javascript
复制
if (value > std::numeric_limits<ValueType>::max())
{
   value = std::numeric_limits<ValueType>::max();
}
else if (value < std::numeric_limits<ValueType>::min())
{
   value = std::numeric_limits<ValueType>::min();
}
ValueType converted = value;
票数 1
EN

Stack Overflow用户

发布于 2011-01-14 19:39:38

这可能与转换本身无关,但与尝试访问无效内存(可能是堆栈损坏或类似情况)有关。你能提供一些代码片段吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4690545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档