簡體   English   中英

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

[英]How do I prevent/suppress SIGFPE in C++?

我正在嘗試將double轉換為float以及dll中的各種整數類型,該dll被用作Game Maker擴展程序。 如果雙精度數不適合目標類型的范圍,則不需要明智的結果,因此我只使用了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;
}

由於您使用的是DLL,您確定DLL的編譯方式與程序預期的相同嗎? 也許一些32/64位不匹配?

同樣,當轉換時出現下溢/上溢時,SIGFPE也可以提高。

您可以通過使用_FPU_SETCW (位於fpu_control.h )設置掩碼來啟用/禁用由此溢出引起的信號(我猜是Game Maker啟用了此功能,而您的測試程序未啟用)。

我從來沒有嘗試過,我不確定mingw也有這個,但是我希望這會有所幫助。

編輯:

為什么不確保不會發生溢出?

就像是:

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;

好的解決方案是通過在轉換之前確保源值在目標類型的范圍內來正確執行轉換。 所以我的問題代碼可以像這樣糾正:

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 Numeric Conversion庫的文檔包含一些有關標准如何定義某些轉換的有用信息

感謝rve在他的回答中提供了正確的建議,但是不幸的是他的示例代碼有缺陷,我想添加一些對我有幫助的指針。

可能與轉換本身無關,但與嘗試訪問無效的內存(可能是堆棧損壞或類似問題)有關。 您可以提供一些代碼片段嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM