web-dev-qa-db-ja.com

「セグメンテーション違反」はシステムエラーですか、プログラムのバグですか?

現在、系統発生的分散分析を実行する統計モデリングスクリプトを実行しています。データセット全体を分析すると、スクリプトは正常に実行されます。しかし、サブセットを取得すると、分析を開始しますが、セグメンテーション違反ですぐに終了します。これが私の側の問題(サンプルデータセットから分析用に小さい)やスクリプトのバグによるものか、これが私のLinuxシステムと関係があるのか​​、グーグルで実際に理解することはできません。私はそれをメモリへのデータの書き込みに関係していると読みましたが、それよりも大きなデータセットですべてがうまくいくのはなぜですか?私はグーグルを使ってより多くの情報を見つけようとしました、しかしこれはそれをより複雑にしました。

事前にご説明いただきありがとうございます。

14
TUnix

(tl; dr:それはほぼ間違いなく、プログラムまたはそれが使用するライブラリーのバグです。)

セグメンテーション違反は、メモリアクセスが不正であったことを示します。つまり、発行された要求に基づいて、CPUはページフォールトを発行します。これは、要求されたページが常駐していないか、要求と矛盾する権限を持っているためです。

その後、カーネルは、このページについて単に何も知らないのか、まだメモリにないのでそこに配置するのか、または特別な処理(たとえば、コピーオン)を実行する必要があるのか​​を確認します。 -writeページは読み取り専用であり、このvalidページフォールトは、コピーしてアクセス許可を更新する必要があることを示す場合があります。 マイナーとメジャーの比較についてはWikipedia を参照してください(例: デマンドページング )と無効なページフォールト。

セグメンテーション違反を取得すると、無効なケースが示されます。ページがメモリ内にないだけでなく、プロセスには仮想アドレス空間のそのページが論理的にマッピングされていないため、カーネルは実行する修正アクションもありません。そのため、これはほぼ間違いなく、プログラムまたはその基盤となるライブラリのいずれかにバグがあることを示しています。たとえば、プロセスに対して無効なメモリへの読み書きを試みています。アドレスがたまたま有効だった場合、スタックの破損や他のデータへの落書きが発生した可能性がありますが、unでマップされたページの読み取りまたは書き込みは、ハードウェア。

小さなデータセットではなく大きなデータセットで機能する理由は、そのプログラムに完全に固有です。それは、おそらくそのプログラムのロジックのバグであり、何らかの理由で小さなデータセットに対してのみトリップします(たとえば、データセットにエントリの総数を表すフィールド。更新されていない場合、プログラムは他の健全性チェックを行わない場合、割り当てられていないメモリを盲目的に読み取る可能性があります)。

単にソフトウェアのバグである可能性よりも数桁少ない可能性がありますが、セグメンテーション違反は、メモリの障害、CPUの障害、またはエラッタを介したハードウェアのトリップなどのハードウェアの問題の指標となる場合もあります(例として こちら )。

ハードウェアの障害が原因でsegfaultを取得すると、しばしば動作する場合がありますが、物理的なRAMの不良ビットは、他に何も実行しない場合、プログラムの繰り返し実行で同じようにマッピングされる可能性がありますmemtest86 +を起動してRAMの障害をチェックし、Prime95などのソフトウェアを使用してCPUのストレステストを行うことで、この可能性をほとんど排除できます(FP math FMA実行ユニットを含む)。


Gdbのようなデバッガーでプログラムを実行し、セグメンテーション違反が発生したときにバックトレースを取得できます。これは原因を示している可能性があります。

% gdb --args ./foo --bar --baz
(gdb) r   # run the program
[...wait for segfault...]
(gdb) bt  # get the backtrace for the current thread
36
Chris Down

アクセスが許可されていないメモリ位置にアクセスすると、セグメンテーション違反が発生します。多くの場合、これはnullポインターの逆参照、または割り当てられたメモリの範囲外のメモリへのアクセスが原因です。

完全なデータセットは機能するが、サブセットが機能しない場合:

  • データセットにフィーチャが含まれていないことをプログラムが適切に処理しているかどうかを確認します(データセットに存在するフィーチャに基づいて配列を割り当て、その後、データセット全体の既知のフィーチャリストに基づいて長さを想定しますか?)
  • 空のグループがあると問題が発生しますか?一般に、配列が空の場合に明らかになる、ある種のオフバイワンエラー?
5
kutschkem

どちらかが原因である可能性があります。ほとんどの場合、Chrisが説明したように、ソフトウェアのバグですが、一部のハードウェアの問題(特にメモリと電源の不良)がセグメンテーションフォールトを引き起こす可能性もあります。不正な値がメモリから読み取られると、破損した命令の実行、破損したポインタの読み取り、破損したページテーブルの使用などが発生し、これらすべてがsegfaultにつながります。

ただし、ハードウェアベースのsegfaultは非常に多く、ランダムであり、数百万分の1ビットのフリッピングイベントが原因で発生します(システムがそれよりも不安定な場合、起動のポイントに到達します)。一方、ソフトウェアのバグが原因のセグメンテーションフォールトは、完全に再現可能です。

3
hobbs