2017-12-28 30 views
0

誰かがこの「無限の」ループを素早くsegfaultsする理由を説明できますか?例えば は、我々はこの機能を持っているとしましょう:bashスクリプトのsegfaults on brk()

#!/bin/bash 

foo() { 
    foo 
}; foo 

これは8-10秒後にセグメンテーションフォールト。 straceのを経由して調べる、我々はBRK(の多くを見ることができます)呼び出し:

brk(0x2e11000)       = 0x2e11000 
brk(0x2e12000)       = 0x2e12000 
brk(0x2e13000)       = 0x2e13000 
brk(0x2e14000)       = 0x2e14000 
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x7ffcddf5ff68} --- 
+++ killed by SIGSEGV +++ 
Segmentation fault 

私の質問は以下のとおりです。メモリ空間にマップされていない領域にアクセスしようとしているので、

  1. は、このセグメンテーションフォルトである(経由brk)?
  2. 「はい」の場合、なぜそれにアクセスしようとしていますか?
  3. ここではmalloc()をおすすめしますか?
  4. これに余分な/トリビアの情報がある場合、それは高く評価されます。
+1

私は、再帰のスタック破損に関連していると思います。 – Inian

答えて

3
  1. brkは関連しません。それはスタックスペースを使い果たしたために失敗します。利用可能なスタックをulimit -s 512; ./yourscriptで減らすと、より速くクラッシュすることがわかります。

  2. 無限に再帰的な関数があり、bashがテールコールの最適化を行わないため、すべてのスタック領域を浪費します。

  3. すでにmalloc(またはそのbash固有のバージョン)を使用しています。 mallocは、Cライブラリ関数であり、システムコールではないため、straceには表示されません。割り当てられたメモリに問題はありませんが、スタック領域が不足しています。

  4. brkは、無限回帰に関連する無限のメタデータの一部を保存するために使用されますが、それだけでは不十分です。

    無限再帰関数のクラッシュは、最適化されていない無限再帰がある場合に、すべての言語でさまざまな形式で発生します。 Javaでvoid foo() { foo(); }、またはPythonでdef foo(): foo()を試してみてください。

+0

素晴らしい答え。ありがとう! – py9

0

リソースがなくなるまでスタックが成長しているように見えます。つまり、再帰問題です。

brk()コールを見ると、プロセスのデータセグメントの最後が変更されていることがわかります。プログラムブレークを増やすと、プロセスにメモリを割り当てることになりますが、無尽蔵の電源はありません。あなたが使い果たしたとき、それはクラッシュします。

しかし、3番目の質問では、ドキュメントの注釈セクションでさえ、malloc()が良い選択であることを示しています。