1. ホーム
  2. c++

[解決済み] なぜセグメンテーションフォールトは回復できないのですか?

2022-10-22 04:29:31

質問

以下 以前の私の質問 のように、ほとんどのコメントで、「とにかくやめてください、手詰まり状態です、すべてを破棄して最初からやり直さなければなりません」と書かれています。 また、次のような安全な回避策もあります。 .

私が理解できないのは なぜ セグメンテーション フォルトは、本質的に回復不可能です。

保護されたメモリへの書き込みが捕捉される瞬間 - そうでない場合は SIGSEGV は送信されません。

保護されたメモリへの書き込みの瞬間を捕らえることができるのであれば、なぜ - 理論的には - ある低レベルでそれを元に戻し、SIGSEGV を標準的なソフトウェア例外に変換させることができないのか、私には理解できません。

セグメンテーション フォルトの後、プログラムが未確定の状態にある理由を説明してください。 前に の前に投げられたからです (私はおそらく間違っていて、その理由はわかりません)。もし、フォルトが投げられた後であれば、保護されたメモリを 1 バイトずつ変更するプログラムを作成し、セグメンテーション フォルトを取得し、最終的にカーネルを再プログラムすることができます。

  1. セグメンテーション フォルトは正確にいつ発生するのか (= いつが SIGSEGV が送信されたとき) ですか?
  2. なぜ、その時点以降、プロセスが未定義の動作状態になっているのでしょうか?
  3. なぜ回復不能なのですか?
  4. なぜ この解決策 はその回復不可能な状態を回避するのでしょうか?それもあるのでしょうか?

どのように解決するのですか?

<ブロッククオート

セグメンテーションフォールトは、具体的にいつ発生するのでしょうか (= SIGSEGV はいつ送信されるのでしょうか)。

境界外の配列にアクセスしたり、無効なポインタをデリファレンスしたりするなど、アクセス権のないメモリにアクセスしようとしたときです。その際、シグナル SIGSEGV Segmentation faultは主に*nix系で使われる用語で、Windowsではaccess violationと呼ばれています。

なぜその時点以降、プロセスが未定義の動作状態になるのでしょうか?

プログラム内の1つまたはいくつかの変数が期待通りに動作しなかったからです。例えば、いくつかの値を格納するはずの配列があったとして、そのすべての値に対して十分な領域を割り当てなかったとします。そのため、割り当てた値だけが正しく書き込まれ、残りの値は配列の枠外に書き込まれ、値を保持することができません。OSは、アプリケーションが機能するために、これらの境界外の値がどれほど重要であるかを正確に知ることができるのでしょうか?OS はその目的について何も知らないのです。

さらに、許可されたメモリの外への書き込みは、しばしば他の無関係な変数を破損する可能性があり、これは明らかに危険で、任意のランダムな動作を引き起こす可能性があります。このようなバグは、しばしば追跡が困難です。たとえば、スタック オーバーフローは、エラーが保護メカニズムによって捕捉されない限り、隣接する変数を上書きしがちな、そのようなセグメンテーション エラーです。

OS も仮想メモリ機能もない、生の物理メモリだけの「ベアメタル」マイクロコントローラ システムの挙動を見ると、たとえば無関係な変数を上書きするなど、言われたとおりに黙々と実行し、そのまま継続します。その結果、アプリケーションがミッションクリティカルである場合には、悲惨な動作を引き起こす可能性があります。

なぜ回復できないのでしょうか?

OSがあなたのプログラムが何をすることになっているのか知らないからです。

上記のベアメタル シナリオでは、システムはセーフ モードに移行して処理を継続するほど賢明である可能性があります。自動車や医療技術などの重要なアプリケーションは、それ自体が危険であるため、単に停止したりリセットしたりすることは許されません。むしろ、制限された機能で家に引きずり戻ろうとするでしょう。

なぜこのソリューションでは、その回復不可能な状態を回避できるのでしょうか?また、そのようなことはないのでしょうか?

その解決策は、エラーを無視して続けているだけです。原因となった問題を解決しているわけではありません。非常に汚いパッチであり、一般的にsetjmp/longjmpは非常に危険な関数なので、いかなる目的でも避けるべきです。

私たちは、セグメンテーションフォールトが 症状 ではなく、バグの 原因 .