インディアナ大学インディアナ大学インディアナ大学インディアナ大学

このページでは、

  • 概要
  • 一般的なsegfaultsの例
  • 範囲外の配列参照を見つける
  • シェルの制限をチェック
  • デバッガを使用して診断します。segfaults

概要

セグメンテーション障害(別名segfault)は、プログラムがクラッシュする原因となる一般的な条件です。coreという名前のフ Segfaultsは、プログラムが不正なメモリ位置を読み書きしようとしていることが原因です。

プログラムメモリは、プログラム命令のテキストセグメント、コンパイル時に定義された変数と配列のデータセグメント、サブルーチンと関数で定義された一時的な(または自動)変数のスタックセグメント、およびmalloc(C)およびallocate(Fortran)などの関数によって実行時に割り当てられた変数のヒープセグメントに分けられる。 詳細については、”プログラムセグメントについて”を参照してください。

segfaultは、変数への参照がその変数が存在するセグメントの外側にある場合、または読み取り専用セグメント内の場所への書き込みが試行された場 実際には、segfaultsは、ほとんどの場合、存在しない配列要素を読み書きしようとしたり、ポインタを使用する前にポインタを適切に定義したり、(Cプログラムで)変

一般的なsegfaultsの例

  • たとえば、以下に示すようにmemset()を呼び出すと、プログラムがsegfaultになります。
    memset((char *)0x0, 1, 100);
  • 次の三つのケースは、配列関連のsegfaultsの最も一般的なタイプを示しています。

    ケースA
    /* "Array out of bounds" error valid indices for array foo are 0, 1, ... 999 */ int foo; for (int i = 0; i <= 1000 ; i++) foo = i;

    ケースb

    /* Illegal memory access if value of n is not in the range 0, 1, ... 999 */ int n; int foo; for (int i = 0; i < n ; i++) foo = i;

    ケースc

    /* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2 = 1.0;
    • ケースaでは、配列fooindex = 0,1, 2, ... 999forfoofooが存在するメモリセグメントの外側にある場合、segfaultになります。 たとえそれがsegfaultを引き起こさなくても、それはまだバグです。
    • ケースBでは、integer n 任意のランダムな値にすることができます。 ケースAと同様に、0, 1, ... 999の範囲にない場合、segfaultが発生する可能性があります。 それがそうであるかどうかにかかわらず、それは確かにバグです。
    • ケースCでは、変数foo2foo2foo2おそらくsegfaultになります。
  • segfaultsにつながる別の一般的なプログラミングエラーは、ポインタの使用における見落としです。 たとえば、C関数scanf()は、変数のアドレスを第二のパラメータとして期待しているため、次のようにすると、プログラムがsegfaultでクラッシ:
    int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */

    変数foo10000000000foo

  • segfaultは、プログラムが許可されていない方法でメモリ位置を操作しようとすると発生します(たとえば、読み取り専用の場所を書き込もうとすると、segfault
  • Segfaultsは、プログラムがスタック領域を使い果たしたときにも発生する可能性があります。 これはあなたのプログラムのバグではないかもしれませんが、代わりにあなたのシェルがスタックサイズの制限を小さすぎるように設定してい

範囲外の配列参照の検索

ほとんどのFortranコンパイラには、実行時にすべての配列参照に対して境界チェックを行うコードを挿入するオプ アクセスが配列に定義されているインデックス範囲外にある場合、プログラムは停止し、これがどこで発生するかを通知します。 ほとんどのFortranコンパイラでは、オプションは-C-checkの後にキーワードが続きます。 正確なオプションを取得するには、コンパイラのユーザーガイドを参照してください。 プログラムが遅くなるため、デバッグ時にのみ境界チェックを使用してください。 一部のCコンパイラには境界チェックオプションもあります。

シェル制限の確認

上記の最後の例で述べたように、segfaultの問題のいくつかは、プログラムのバグによるものではなく、システムメモリ制限が低 通常、この種の問題を引き起こすのはスタックサイズの制限です。 メモリ制限を確認するには、bashkshlimitcshcshcshcshcshcshcshcshtcsh。 Stacksizeを高く設定してから、プログラムを再実行してsegfaultが消えているかどうかを確認してください。

デバッガを使用してsegfaultsを診断します

他の方法で問題を見つけることができない場合は、デバッガを試してみてください。 たとえば、GNUのよく知られているデバッガGDBcoregdb corebacktraceコマンドを使用して、プログラムがクラッシュしたときの場所を確認します。 この単純なトリックは、コードのその部分に焦点を当てることができます。

coregファイルでbacktrace-gフラグを使用する必要があるため、ソースコード行に関する情報が実行可能ファイルに 詳細については、Emacs内でGDBを使用してC orC++プログラムをデバッグするためのステップバイステップの例を参照してください。

関連ドキュメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です