3

という名前の構造体へのポインター内にポインターがある C コードをデバッグしていますboard。ボードを印刷している機能があります:

static void board_print(board *b){
    int i,j;
    char data;
    for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
            data = b->data[i * size + j];
            if(data){
                printf("X ");
            }else{
                printf("O ");
            }
        }
        printf("\n");
    }
}

ここが奇妙な部分です。最初の for ループの先頭で最初にブレークポイントにヒットすると、すべて問題なく、データは正しく、すべてのポインターは次のように機能します。

最初

次に、i と j を 0 にして初めてループに入りb->data[0]ます。2 ステップ前のように、完全に有効なはずです。突然、ラインを踏むとすぐにdata = b->data[i * size + j];、データ ポインターがヌル ポインターに変わります。この行を実行すると、(明らかに) 以下に示すように、不正なアクセス エラーが発生します。

2番目

その理由は何ですか?私は以前に C を使用したことがあり、それについてはかなり理解していますが、シングルスレッドの単純な C プログラムにステップインしているときに、ポインタ値が突然 null に変化するのを見たことはありません。Apple LLVM Compiler 4.1 を使用してコンパイルし、lldb を使用してデバッグしています。これは、XCode 4.5 のデフォルトです。

更新: gcc でコンパイルし、gdb でデバッグした場合と同じ動作が観察されました。私の側ではほぼ100%エラーですが、コードの何が問題なのかわかりません..

更新 #2: gcc/gdb でさらに奇妙なことに気付きました。行を実行する直前にdata = b->data[i * size + j];、問題なくデバッガーからすべてにアクセスできます。その行を実行した直後は、b->dataステップ実行の直前にアクセスした値を含め、完全にアクセスできません。

三番

$4 = ...デバッガーで正常に実行された行の後、その行をまたがりました。次に、上記のようにさまざまなアドレス指定エラーが発生しました。私は本当に何が起こっているのか分かりません...

更新 #3:非常に奇妙なことに気付きました。ここで、まず私が実装した修正を見てください。名前付きの変数をdata完全に削除すると、これは問題なく動作し始めました。

第4

ここで、更新 #2 でアップロードしたスクリーンショットをよく見てください。という名前のローカル変数に値を割り当てた直後に、そのアドレスdataも変更されます。b->data割り当ての副作用のように見えます。しかし、その背後にある理由が何であるかはわかりません。

4

1 に答える 1

2

明らかに何か/誰かがボード構造のプロパティ「データ」を変更します。

なんで ?私は3つの理由しか見ることができません:

  • アプリケーションはマルチスレッドであり、他のスレッドがデータポインタをNULLに更新します(これはあなたの場合ではなく、1つのスレッドのみを使用しています。申し訳ありませんが気づいていませんでした)。

  • ボード構造はスタックから割り当てられますが、内容はもう有効ではありません...例:ローカル変数のポインターは返されますが、返されるときに変数(構造体)は破棄されます(これはローカル変数であるため)ポインタ...

  • ボード構造はヒープから割り当てられてから解放され、最後にこの解放されたポインタが引き続き使用されます。ヒープメモリが他の何かによって破損しています...

私の推測:よくある間違いである2番目のポイント

簡単な質問です。ボード構造体はHEAPまたはSTACKメモリに格納されていますか?

于 2012-12-29T16:09:16.763 に答える