【问题标题】:Enabling floating point exceptions on MinGW GCC?在 MinGW GCC 上启用浮点异常?
【发布时间】:2015-05-11 18:57:54
【问题描述】:

如何在缺少feenableexceptMinGW GCC 上启用浮点异常?即使reasonably complete solutions 也没有真正抓住这一点,尽管他们似乎打算这样做。我更喜欢与未来出现的任何标准接近的最少代码。最好,代码应该在有和没有 SSE 的情况下工作。一个完整的解决方案,展示如何启用硬件信号,捕获它,并重置它是可取的。必须使用高优化级别和完整的迂腐错误和警告进行干净编译。在单元测试场景中多次捕获的能力很重要。有几个问题providepartialanswers

【问题讨论】:

    标签: gcc signals mingw-w64 floating-point-exceptions


    【解决方案1】:

    这似乎在我的机器上工作。使用 -fnon-call-exceptions 在 MinGW GCC 中编译它。它还没有完全最小化。

    #include <xmmintrin.h>
    #include <cerrno>
    #include <cfenv>
    #include <cfloat> //or #include <float.h> // defines _controlfp_s
    #include <cmath>
    #include <csignal>
    
    #ifdef _WIN32
    void feenableexcept(uint16_t fpflags){
     /*edit 2015-12-17, my attempt at ASM code was giving me
      *problems in more complicated scenarios, so I
      *switched to using _controlfp_s. I finally posted it here
      *because of the upvote to the ASM version.*/
     /*{// http://stackoverflow.com/questions/247053/
      uint16_t mask(FE_ALL_EXCEPT & ~fpflags);
      asm("fldcw %0" : : "m" (mask) : "cc");
     } //https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html   */
     unsigned int new_word(0);
     if (fpflags & FE_INVALID) new_word |= _EM_INVALID;
     if (fpflags & FE_DIVBYZERO) new_word |= _EM_ZERODIVIDE;
     if (fpflags & FE_OVERFLOW) new_word |= _EM_OVERFLOW;
     unsigned int cw(0);
     _controlfp_s(&cw,~new_word,_MCW_EM);
    }
    #endif
    
    void fe_reset_traps(){
     std::feclearexcept(FE_ALL_EXCEPT); //clear x87 FE state
    #ifdef __SSE__
     _MM_SET_EXCEPTION_STATE(0); // clear SSE FE state
    #endif
     feenableexcept(FE_DIVBYZERO|FE_OVERFLOW|FE_INVALID); // set x87 FE mask
    #ifdef __SSE__
     //set SSE FE mask (orientation of this command is different than the above)
     _MM_SET_EXCEPTION_MASK(_MM_MASK_DENORM |_MM_MASK_UNDERFLOW|_MM_MASK_INEXACT);
    #endif
    }
    
    void sigfpe_handler(int sig){
     std::signal(sig,SIG_DFL); // block signal, if needed
     std::cerr<<"A floating point exception was encountered. Exiting.\n";
     fe_reset_traps(); // in testing mode the throw may not exit, so reset traps
     std::signal(sig,&sigfpe_handler); // reinstall handler
     throw std::exception();
    }
    
    fe_reset_traps();
    std::signal(SIGFPE,&sigfpe_handler); // install handler
    std::cerr<<"before\n";
    std::cerr<<1.0/0.0<<"\n";
    std::cerr<<"should be unreachable\n";
    

    我确信它并不完美。让我们听听其他人的贡献。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-28
      相关资源
      最近更新 更多