2016-12-20 10 views
0

Cの動的メモリ割り当てを学習するのは難しいです。これはmainにあります。割り当てられたメモリからメモリの値を設定する

int *a = malloc(sizeof(int)); 
printf("%d %d %d\n", *a, *(a + 1), *(a + 2)); 
*a = 4; 
printf("%d %d %d\n", *a, *(a + 1), *(a + 2)); 
a = realloc(a, sizeof(int) * 2); 
printf("%d %d %d\n", *a, *(a + 1), *(a + 2)); 
*(a + 1) = 8; 
printf("%d %d %d\n", *a, *(a + 1), *(a + 2)); 
*(a + 2) = 16; 
printf("%d %d %d\n", *a, *(a + 1), *(a + 2)); 

あなたは私が〜8バイトの新しいサイズにaを再割り当て見ることができるようにそれは...

7417176 7405760 706735178 
4 7405760 958328410 
4 7405760 958328410 
4 8 958328410 
4 8 16 

をプリントアウトします。しかし私は最初に*(a + 2)を16に初期化しましたが、わかりましたので、私は〜8バイトしか割り当てられませんでした(少なくとも12バイト必要です)。これはどのように可能ですか?

+3

Cでようこそ、ここでは、メモリ管理について話す必要があります。 UBは 'printf()'、 '*(a + 1)'への最初の呼び出し時には範囲外です。また、あなたが '*(a + 1)'を初期化しなかったので、あなたは 'printf()'への2回目の呼び出しでUBを持っています。 Cでコード化しようとする前に、Cに関する何かを読むべきです。 – Stargateur

+2

'*(a + 1)':1番目:範囲外の値を読み込みます。 2:初期化されていない値を読み込みます。 – BLUEPIXY

+0

@Stargateurええ、私は「目的」にinit *(a + 1)をしませんでした。新しいメモリを割り当てると、値を初期化しませんでした。だから私はこのメモリが私の価値であることを知ることができます。 – Ortimh

答えて

1

プログラムに割り当てられていないメモリにアクセスすると、プログラムの動作が未定義になります。いくつかの詳細を見てみると

int *a = malloc(sizeof(int)); 

// This part is fine. It will try to allocate the amount of memory 
// needed for storing exactly 1 int. It will assign the pointer a with 
// with a value that points to the allocated memory. 

しかし、mallocが失敗する可能性があります(すなわち、必要なメモリ量を割り当てることができない)ので、あなたはそれが失敗したかどうかを確認する必要があります。 mallocが失敗するとNULLを返します。だから、追加する必要があります。

if (a == NULL) 
{ 
    // malloc failed... 
    // print error 
    exit(1); 
} 

次の行は次のとおりです。

printf("%d %d %d\n", *a, *(a + 1), *(a + 2)); 

// This is undefined behavior: 
//  *a will read the value of the memory just malloc'ed as an int 
//  In principle that is OK but since you didn't initialize the 
//  memory, it is still undefined behavior 
// 
//  *(a+1) and *(a+2) will read memory after the memory malloc'ed 
//  So you access memory not allocated to you. That is undefined 
//  behavior 

それでは、あなたがすべきことは1にある)最初のメモリと、あなたに割り当てられた2)のみアクセスメモリを初期化します。同様に:

*a = 42; 
printf("%d\n", *a); 

次の行:

a = realloc(a, sizeof(int) * 2); 

// In principle this is valid. However, it is not good as realloc may 
// fail just like malloc. 

だから、あなたが行う必要があります:コードの残りの部分については

int* temp = realloc(a, sizeof(int) * 2); 
if (temp == NULL) 
{ 
    // Error handling or just exit... 
    free(a); 
    exit(1); 
} 
a = temp; 

あなたは上記のものと同様の問題を抱えています。

しかし私は〜(a + 2)を16に初期化しましたが、私は〜8バイトしか割り当てられませんでした(少なくとも12バイト必要です)。これはどのように可能ですか?

C言語では、行うことすべてが有効であるかどうかはチェックされません。言い換えれば、Cはあなたが求めていることをさせる。有効なものだけを確実に行うことは、あなた自身の責任です。

実行時に、システムがプログラムが不正な処理を行っていることを検出することがあります。もしそうなら、クラッシュ(コアダンプ)が発生します。

しかし、システムがあなたのプログラムが何か違法行為をしていることを検出できない状況がたくさんあります。だからプログラムはちょうど続くでしょう。その結果、あらゆる種類の奇妙なエラーが発生する可能性がありますが、プログラムを実行した最初の100回が正しいかのように見えて、次回に失敗することがあります。それは未定義の振る舞いです....未定義 - あなたは何が起こるか分からないでしょう。

Cでコーディングすると、多くの負担がかかります。 Cで違法行為を行うことは非常に簡単です。法的なことのみを行うことはあなたの責任です。

今日、Cを分析して間違ったコードを見つけるためのツールが多数用意されています。バングラドとカバレッジ。

関連する問題