20
6

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 3 years have passed since last update.

C で「*」をたくさんつけるとコンパイラが死ぬ

Last updated at Posted at 2021-08-06

これは何?

C++でアスタリスクをつけすぎると端末が落ちる という素晴らしい記事がある。

ふと、もっと簡単なコードでたくさん * をつけられるな、という事に気づいたので試した。

* のつけかた

こういう感じ。

c
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int main()
{
    intptr_t ********a;
    *(intptr_t*)&a = (intptr_t)&a;
    printf("a=%p, *..*a=%jd\n", a, ********a);
    return 0;
}

ほんのり未定義動作感があるが、実用上は悪くない。
実行すると

a=0x7ffee5828808, *..*a=140732748957704

みたいな出力が得られる。

限界に挑戦。

ruby でこんなコードを書いた。

ruby
# CC="gcc-7"
CC="clang"

def test_aster(n)
  aster = "*"*n
  src=<<~"SRC"
  #include <stdio.h>
  #include <stdlib.h>
  #include <stddef.h>

  int main()
  {
      intptr_t #{aster}a;
      *(intptr_t*)&a = (intptr_t)&a;
      printf("a=%p, *..*a=%jd\\n", a, #{aster}a);
      return 0;
  }
  SRC

  File.open( "hoge.c", "w" ){ |f| f.puts(src) }
  puts %x((time #{CC} -O0 hoge.c ) && time ./a.out)
  puts( "n=#{n}  err = #{$?}")
  $?==0
end

n=1
loop do
  break unless test_aster(n)
  n*=2
end

a = [*(n/2)..n]
p(a.bsearch do |n|
  !test_aster(n)
end)

gcc-7 の場合。

gcc-7 (Homebrew GCC 7.5.0_4) 7.5.0 で試した。

幸い端末が死んだりはせず、最終的には

135275

が出力された。つまり、13万5274個までは OK。13万5275個で死ぬ。

ちなみに結果が出るまで数時間を要した。一回のコンパイルに 20分 以上かかることがある。

遺言はこうだった。

gcc-7: internal compiler error: Segmentation fault: 11 (program cc1)
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://github.com/Homebrew/homebrew-core/issues> for instructions.

「メモリ確保に失敗したので断念します」みたいなちゃんとしたエラー終了ではなく、セグフォ。
メモリ確保に失敗していることに気づかないまま先に進んじゃったのかな。

gcc-11 の場合。

gcc-11 (Homebrew GCC 11.2.0) 11.2.0 で試した。

幸い端末が死んだりはせず、最終的には

209672

が出力された。つまり、20万9671個までは OK。20万9672個で死ぬ。

gcc-7 よりちょっと多いね。

ちなみに結果が出るまで gcc-7 の場合よりももっと長い時間を要した。

gcc-11 の遺言は

gcc-11: internal compiler error: Segmentation fault: 11 signal terminated program cc1
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://github.com/Homebrew/homebrew-core/issues> for instructions.

だった。
こちらもセグフォ。南無南無。

clang

Apple clang version 12.0.5 (clang-1205.0.22.11) で試した。

こちらも端末が死んだりはせず、最終的には

2463

が出力された。つまり、 2462個までは OK。2463個で死ぬ。

gcc と比べるとだいぶ少ないけど、困る人はいないだろう。

clang の遺言は長くてこんな感じ。

clang: error: unable to execute command: Illegal instruction: 4
clang: error: clang frontend command failed due to signal (use -v to see invocation)
Apple clang version 12.0.5 (clang-1205.0.22.11)
Target: x86_64-apple-darwin20.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
clang: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /var/folders/zy/xw4cyzx50_b2h0l86k76qh900000gn/T/hoge-590b89.c
clang: note: diagnostic msg: /var/folders/zy/xw4cyzx50_b2h0l86k76qh900000gn/T/hoge-590b89.sh
clang: note: diagnostic msg: Crash backtrace is located in
clang: note: diagnostic msg: /Users/nabetani/Library/Logs/DiagnosticReports/clang_<YYYY-MM-DD-HHMMSS>_<hostname>.crash
clang: note: diagnostic msg: (choose the .crash file that corresponds to your crash)
clang: note: diagnostic msg: 

********************

Illegal instruction とは、穏やかでない。

Visual Studio

Visual Studio 2019 の cl も、Visual Studio 2022 preview の cl も、同じだった。
バージョンは

Microsoft(R) C/C++ Optimizing Compiler Version 19.29.30040 for x64

Microsoft(R) C/C++ Optimizing Compiler Version 19.30.30401 for x64

最終的に 1495 を出力して終わったので、 1494 まで OK。1495 だとコンパイル失敗。

失敗時のメッセージは

fatal error C1026: プログラムの解析でコンパイラ内でスタック オーバーフローが発生しました。プログラムが複雑すぎます。

と、死亡ではなくエラー終了。ちゃんとしている。

コンパイル結果

gcc-7, gcc-11, clang, cl は、いずれも最適化なしの場合、

アセンブラ
	movq	(%rax), %rax
	movq	(%rax), %rax
	movq	(%rax), %rax
	movq	(%rax), %rax
	movq	(%rax), %rax
	movq	(%rax), %rax
	movq	(%rax), %rax

というように大量の movq を生成する(cl の場合はアセンブラの文法が違うけど、実質的に同じ)が、 -O2 にすると一掃される。ちゃんとしているね。

20
6
2

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
20
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?