0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Mac上でg++でコンパイル、実行するとSIGILLが出るコード

Last updated at Posted at 2018-03-06

はじめに

Mac上でSIGSEGVが出そうなコードをg++でコンパイル、実行するとSIGILLが出たのでメモ。

再現コードはここに置いてある。

現象

  • 再現環境1
    • macOS High Sierra 10.13.3
    • g++ (Homebrew GCC 7.2.0) 7.2.0
    • 3.3 GHz Intel Core i5

以下のコードをg++ -march=native -O3でコンパイル、実行するとSIGILLが出る(a.out)。

test.cpp
//------------------------------------------------------------------------
#include <iostream>
#include <string>
#include <fstream>
//------------------------------------------------------------------------
#ifdef CASE_C
inline   // if activate this line, a program works
#endif
void func2(int a[81]) {
  int n[6][9][9] = {};
  for (int i = 0; i < 9; i++) {
    int i1 = a[i];
    int i2 = a[i + 9];
    n[0][i1][i2]++;
    n[0][i2][i1]++;
  }
  std::string s1[3];
  for (int j = 0; j < 3; j++) {
    for (int i = 0; i < 6; i++) {
      s1[j][i] = '0' + n[j][0][i];
    }
  }
}
//------------------------------------------------------------------------
void
func(void){
#ifndef CASE_B
  std::ifstream ifs("test.dat");//with this, the program aborts with SIGILL
#endif
  int a[81];
  func2(a);
}
//------------------------------------------------------------------------
int
main(void) {
  func();
}
//------------------------------------------------------------------------

以下は実行結果

$  g++ -march=native -O3 test.cpp -o a.out
$ ./a.out
zsh: illegal hardware instruction  ./a.out

詳細

  • コードの中に全く使われないstd::ifstreamの宣言があるが、これを削除するとSIGILLは出ない(-DCASE_Bをつけてコンパイルするとできるb.out)。
  • main関数から二回の関数呼び出しがあるが、最後に呼ばれる関数にinline指定をするとSIGILLがでない(-DCASE_Cをつけてコンパイルするとできるc.out)。
  • -march=nativeを外したり、最適化レベルを下げても発生しない。
  • clang++では出ない。
  • Linuxだと普通にSIGSEGVが出る
  • gdbが言うにはaddl $0x1,0x60(%rsp,%rdx,4) で止まっているらしい。普通にアクセス違反っぽいんだけど・・・

疑問点

  • SIGSEGVが出るのはわかるけれど、なぜSIGILLが出るんだろう?
  • Macのバグなの?GCCのバグなの?

追記

一行で再現するコードを作った。

test.cpp
int main(void) {
  __asm__("movl  $0, 0(%rbp,%rdx,4)");
}

これをデフォルトオプションでコンパイル、実行すると、g++でもclang++でもSIGILLが出る。

$ g++ --version 
g++ (Homebrew GCC 7.2.0) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ test.cpp
$ ./a.out
zsh: illegal hardware instruction  ./a.out

$ clang++ --version 
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ clang++ test.cpp
$ ./a.out
zsh: illegal hardware instruction  ./a.out

というわけで、

  • g++の問題ではない(clang++でも出る)。
  • コンパイルオプションや、std::stringstd::ifstreamの問題ではない(不適切なmovlを出すための条件)
  • LinuxではSIGBUSが、Windows (CYGWIN)ではSIGSEGVが出るのに、MacではSIGILLが出る

ということがわかった。

・・・なぜ?

  1. 同じバージョンのOS、GCCで、石だけCore i7な環境でも再現した。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?