3

浮動小数点エラーが発生したときにコードを終了させたい。linux-gcc では「feenableexcept()」関数が機能しますが、OSX では利用できません。OS X で gcc を使用する場合、( Mac OS X Intel で浮動小数点割り込みを有効にする ) で採用されたアプローチは、gcc を使用する場合は問題なく機能しますが、clang を使用する場合は機能しません。

コード例:

#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <xmmintrin.h>

void handler(int sig) {
  void *array[10];
  size_t size;
  size = backtrace(array, 10);
  fprintf(stderr, "Error: signal %d:\n", sig);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
  exit(1);
}

int main(int argc, char **argv)
{
  _MM_SET_EXCEPTION_MASK( ( _MM_EXCEPT_INVALID |
                _MM_EXCEPT_DENORM |
                _MM_EXCEPT_DIV_ZERO |
                _MM_EXCEPT_OVERFLOW |
                _MM_EXCEPT_UNDERFLOW |
                _MM_EXCEPT_INEXACT ) );

  signal(SIGSEGV, handler);
  signal(SIGFPE, handler);

  std::cout<<"Perform 1.0/0.0"<<std::endl;
  double a = 1.0/0.0;
  std::cout<<"1.0/0.0 didn't kill program, result is "<<a<<std::endl<<std::endl;

  int* foo = (int*) - 1 ;// make a bad pointer
  std::cout<<"Attempting to print a bad pointer"<<std::endl;
  printf("%d\n", *foo);
  std::cout<<"Bad pointer didn't kill program."<<std::ends;
}

gcc5 を使用してコンパイルすると、結果は次のようになります。

Perform 1.0/0.0
Error: signal 8:
0   a.out                               0x000000010f97cb7f _Z7handleri + 28
1   libsystem_platform.dylib            0x00007fff895c652a _sigtramp + 26
2   ???                                 0x00007fff6eab6568 0x0 + 140735050114408
3   libdyld.dylib                       0x00007fff936a15ad start + 1

素晴らしい。よく働く。ただし、clang (Apple LLVM バージョン 7.3.0 (clang-703.0.29)) を使用してコンパイルすると、結果は次のようになります。

Perform 1.0/0.0
1.0/0.0 didn't kill program, result is inf

Attempting to print a bad pointer
Error: signal 11:
0   a.out                               0x000000010d501d1f _Z7handleri + 31
1   libsystem_platform.dylib            0x00007fff895c652a _sigtramp + 26
2   ???                                 0x00007fff62b7e568 0x0 + 140734849607016
3   libdyld.dylib                       0x00007fff936a15ad start + 1

良くない。FPE を発生させず、コードはただ動き続けました。私は周りを見回しましたが、clang で FPE を上げる方法が見つかりません。誰もこれを経験していますか?ありがとう!

4

2 に答える 2