0

C で Linked List を作成しようとしていますが、不可解な障害によりプログラムがクラッシュしました。

最初にこれを試しました:

typedef struct product_data product_data;

struct product_data {
 int product_code;
 int product_size;
 product_data *next;
};

product_data *products_head = NULL;
product_data *products_tail = NULL;

int main() {
    int newcode = 5;
    int newsize = 5;
    products_head->product_code = newcode;
    products_head->product_size = newsize;
    products_head->next = NULL;

    return 0;
}

残念ながら、プログラムはエラー メッセージなしでクラッシュします。

次に、いくつかの部分を変更しました。

typedef struct product_data product_data;

struct product_data {
 int product_code;
 int product_size;
 product_data *next;
};

product_data *products_head = NULL;
product_data *products_tail = NULL;

int main() {
    product_data *newproduct;
    int newcode = 5;
    int newsize = 5;
    newproduct->product_code = newcode;
    newproduct->product_size = newsize;
    newproduct->next = NULL;

    products_head = newproduct;

    return 0;
}

今回はクラッシュしませんでした。動作しているようです。理由はわかりませんが。

何か案は?

前もって感謝します!

4

5 に答える 5

4

本当にうまくいきません。あなたはまだ無効なポインタを逆参照しています:

product_data *newproduct;
int newcode = 5;
int newsize = 5;
newproduct->product_code = newcode;
newproduct->product_size = newsize;
newproduct->next = NULL;

しかし、最初のバージョンでは、明示的に に設定されたポインターを逆参照NULLしていましたが、本来のようにセグメンテーション違反でクラッシュしました。ここでは、スタック上にあるデータを含むポインターを逆参照していますが、残念ながらクラッシュしません。これは未定義の動作であるため、必ずしもクラッシュする必要はありません。

ポインターが有効なメモリを指すようにする必要があります。

newproduct = malloc(sizeof product_data);
于 2012-06-05T19:42:27.110 に答える
1

products_head にメモリを割り当てる必要があります。現在、NULL に設定しているだけです。ポインターにしないか、malloc を使用してください。

于 2012-06-05T19:42:08.613 に答える
1

最初のサンプルでは、​​NULL ポインターに書き込みます。products_head逆参照する前に、スペースを割り当てる必要があります。何かのようなもの

products_head = malloc(sizeof(product_data));

2番目の例が機能した理由がわかりません。すべきではありません。 newproductは初期化されていない変数であり、どこを指すこともできます。運が良かっただけで、有効なメモリの未使用のチャンクを指していたのかもしれません。

于 2012-06-05T19:42:41.707 に答える
0

これは、機能しなくなるまで機能します。構造体に割り当てられたメモリがまだありません。しかし、運が良ければ、 newproduct は有効なメモリ位置を指します。あなたが直面している問題、product_head は手動で null に設定されました (ただし、すべてのグローバル変数は常に初期化されるため、これは必要ありません)。ただし、スタック変数は初期化されず、アドレス空間で有効な場所をたまたま指していたのは幸運でした (または、あからさまなプログラミングの間違いを見逃す可能性があったのは不運でした)。

printf("%p", newproduct); を使用して、 newproduct の内容を印刷して、それが指している場所を確認できます。残念ながら、この行を挿入すると、プログラムの動作が変わる可能性があります。

于 2012-06-05T19:45:37.803 に答える
0

「->」は、動的に割り当てられた構造内の要素にアクセスすることを意味し、「.」静的に割り当てられた構造体の要素にアクセスするために使用されます。

次に例を示します。

typedef struct product_data product_data;

struct product_data {
    int product_code;
    int product_size;
    product_data *next;
};

product_data *products_head = NULL;
product_data *products_tail = NULL;

int main() {
    /* Allocate memory */
    product_data *newproduct = malloc(sizeof(product_data));
    int newcode = 5;
    int newsize = 5;

    products_head = newproduct;
    newproduct->product_size = newsize;
    newproduct->next = NULL;

    /* free memory */
    free(product_data);

    return 0;
}

ただし、リンクされたリストで作成するすべての新しいノードに対して、メモリを割り当て、そのメモリを解放する必要があることに注意してください。割り当てたすべてのメモリが解放されたことを確認するために使用する良いプログラムは、valgrind です。リンクされたリストを最初に手動で描画しようとして論理エラーが発生した場合は、次のようにします。

      [head]   [tail]
        |        |
        V        V
      [ a ] -> [ b ] -> null

head と tail はどちらもポインターであることを覚えておいてください (したがって、メモリを割り当てる必要はありません。必要なノードを指している必要があります。

ロジックが非常に複雑になるためにまだ問題が発生する場合は、GDB (コマンド ライン デバッガー) を試して学習することをお勧めします。GDB はコードをステップ実行するのに役立ち、何が起こっているかを段階的に確認できます。それが私が最初にデータ構造を作成することを学んだ方法です。

幸運を!

于 2012-06-05T19:53:40.247 に答える