2016-06-12 2 views
1

私は以下のコードでリンクリストを作成しました。ご覧のとおり、mallocを使用してサイズ3のリストを作成しました。しかし、サイズ10以上のforループを実行して初期化して印刷しました。私がコンパイルしたコードを実行すると、取得した結果がCリンクされたリストのサイズはmallocによって制限されていません

#include <stdio.h> 
#include <malloc.h> 
#include <stdlib.h> 

struct node { 
     int value; 
     struct node *next; 
}; 

int main() { 
     //code 
     struct node **head; 
     struct node *curr; 
     curr = (struct node *) malloc(sizeof(struct node)*3); 
     head = &curr; 
     printf("done 1\n"); 
     (*head)->value = 0; 
     (*head)->next = NULL; 
     for(int i = 1; i < 10; i++) { 
       (*head+i-1)->next = (*head+i); 
       (*head+i)->value = i; 
       (*head+i)->next = NULL; 
     } 
     curr = *head; 
     printf("done 2\n"); 
     for(int i = 0; i < 10; i++) { 
       printf("%d\t", (*head + i)->value); 
       //curr = curr->next; 
     } 
     printf("\ndone 3\n"); 
     //free(curr); 
     return 0; 
} 

done 1 
done 2 
0 1 2 3 154208560 842282289 876087600 154744882 808859448 875837236 
done 3 

なぜ私は第四ノードに値を割り当てると、私は実際にサイズ3のリストを作成したときにそれをアクセスすることができています?

ごみの値が5番目から10番目のノードアクセスから印刷されていることがわかりました。しかし、第4ノードはどのように作成されていますか?

P.S:

私は10!= 3であることを知っています。ループをその限界に置くと、コードが正しく実行されました。私は外出時に何が起こるかを見たいと思っていました。私は実際にサイズ3のリストを作成したときに値を割り当てることができたので、第4ノードも作成されていることがわかりました。

これは純粋にsegフォルトを取得するかどうかを確認することです。

+0

'10!= 3' ...私はあなたのコードを正しく理解しています。 – wildplasser

+3

割り当てられたメモリの終わりを超えてアクセスすることは[未定義の動作](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior)です。働くように見えるなど、何かが起こる可能性があります。 – user3386109

+0

それは?私はそれを知らなかった! 私は10!= 3を知っています。ループをその限界に置くと、コードが正しく実行されました。私は外出時に何が起こるかを見たいと思っていました。私は、実際にサイズ3のリストを作成したときに値を割り当てることができたので、第4ノードも作成されていることがわかりました。 – Aspirant9

答えて

7

あなたはundefined behaviorを呼び出しています。これを行うと、プログラムがクラッシュしたり、正常に動作しているように見えたり、一見無作為に動作することがあります。

Cは、配列や割り当てられたメモリに対して何らかの境界チェックを実行しません。それは速くすることの一つです。それはまたあなたがするべきでないことをあなたがすることを可能にするということです。プログラマが「正しいことをやる」ことを信頼しています。

特定のマシンでは、3番目の要素の後にランダムなデータが表示されます。マシン上で同じコードを実行すると、十分なメモリが割り当てられているかのように予想される出力が得られます。また、freeへの呼び出しのコメントを外すと、プログラムがクラッシュします。それは未定義の動作です。

未定義の動作を理解しようとするのは、通常無駄な作業です。それはすべてあなたのコンパイラとそれが実行されるマシンの実装の詳細に依存します。この場合、書き込まれるメモリは、適切に割り当てられたメモリの後のヒープ内の割り当てられていないメモリである可能性があります。 mallocの実装方法によっては、メモリの一部にmallocやその他の関数が正しく動作するために必要なデータが含まれていることがあります。要点は、配列の最後を書き込んでもクラッシュが保証されるわけではないので、注意する必要があります。

+0

あなたが持っている4番目のノードの値があまりにもゴミ値でしたか? – Aspirant9

+0

いいえ、私のマシンは '0 1 2 3 4 5 6 7 8 9'を出力しました。また、 'free'関数呼び出しのコメントを外すと、プログラムがクラッシュします。 – dbush

+0

はい。私はそれを理解していますが、あなたの配列サイズが3の場合、あなたのプログラムは3〜9の値をリストに割り当てることができましたか? これは、プログラムが場所(structノード)への構造体ポインタとしてメモリ位置にアクセスし、最初の場所(node-> value)にアクセスしてデータを保存しようとしたため、データを保存できましたか? – Aspirant9

1

このコードは、さまざまなオペレーティングシステムで異なる動作をします。

10個の整数をすべて割り当ててから正しく印刷することができます。

あなたのコードは、ヒープ上のリストの先頭を3要素だけの割り当てで置きます。

10個の要素すべてに幸運にも、メモリを使用したり、プログラムが4回目にクラッシュすることがあります。

+0

https://ideone.com/でプログラムを実行しています。「0 1 2 3 4 5 6 7 8 9' – sg7

関連する問題