2013-03-29 13 views
5

Cでmalloc.hを学び始めたのは、動的配列を作成することでした。ここでは、コードされていますreallocの何が問題になっていますか?

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

int main() { 
    int *array = (int*)malloc(sizeof(int)); 
    int i, j, val; 
    for (i = 0;; i++) { 
     array = (int*)realloc(array, sizeof(int) + sizeof(*array)); 
     printf("Enter array[%d]=", i); 
     scanf("%d", (array + i)); 
     if (*(array + i) == 0) break; 
    } 
    for (j = 0; j < i; j++) { 
     printf("[%d] = %d\n", j, *(array + j)); 
    } 
    getch(); 
    return 0; 
} 

結果が

Enter array[0]=1 
Enter array[1]=2 
Enter array[2]=3 
Enter array[3]=4 
Enter array[4]=5 
Enter array[5]=6 
Enter array[6]=7 
Enter array[7]=8 
Enter array[8]=9 
Enter array[9]=10 
Enter array[10]=0 
[0] = 1 
[1] = 2 
[2] = 3 
[3] = 4 
[4] = 5 
[5] = 6 
[6] = 7 
[7] = 8 
[8] = 542979931 
[9] = 875896893 

たびにある、>=8値はランダムです。なぜそれが起こるのか分からないので何が間違っていますか?

+1

デバッガを使用してコードをステップバイステップで実行するとどうなりますか? – SecurityMatt

+8

'sizeof()'が最初にどのように動作するのかを学ぶべきです。 –

+1

ヒント: '* array'のデータ型は? 'array'はintへのポインタです。 –

答えて

7

あなたあなたのコードには未定義の動作があります。 sizeof(*array)は右、あなたの全体の配列のサイズを返すことを、あなたが期待

array=(int*)realloc(array,sizeof(int)+sizeof(*array)); 

:私はこれをやって、と仮定しますか?しかし、それは真実ではありません。 sizeofはコンパイル時に計算され、sizeof(*array)は実際にはsizeof(int)と同じです。

ので、この配列の拡張性を作るために、あなたは、要素の現在の数を保持し、追加の変数を持っている必要がありますし、同じような何かを:

current_size_of_arrayは、 forの各ループにインクリメントされます
array=(int*)realloc(array, sizeof(int) + current_size_of_array * sizeof(int)); 

実際にはもう1つの要素を追加します。

+0

ええ、あなたはまったく正しいです。しかし、iveは別のコンパイラで私のコードをちょうどうんざりしてしまいました。それは奇妙なことです...とにかく、説明のためのthaks! – ovnia

+1

@wingsofovnia - それは_undefined behavior_であるため正確に動作します。これは何かが起こる可能性があることを意味します。 –

3

sizeof(*array)は、配列の大きさを示します。これは、intが占めるバイト数を示します。したがって、reallocを呼び出すたびに、2つのint値のメモリだけが割り当てられます。 realloc呼び出しを変更して、sizeof(int)倍の整数値を割り当てます。

2

sizeof(int)+sizeof(*array)

あなたはsizeof(*array)が既に割り当てられたバイト数であると思います。あなたは間違っています、sizeof(*array)は1つのサイズintです。だからあなたはあなたのバッファーをオーバーランさせてしまい、結局それはあなたに問題を引き起こします。

尋ねる前に、すでに割り当てられているサイズを取得する標準的な方法はありません。通常、あなた自身のためにそれを格納する必要があります(またはC++では、vectorのような、よりユーザフレンドリーなインタフェースを使用します(mallocより)。この場合、既存のサイズは必要ありません。必要な新しいサイズはiです。

1

mallocによって割り当てられたメモリブロックのサイズは、ライブラリには知られていますが(freeにはポインタが必要です)、その番号を戻すポータブルな方法はありません。他の変数に現在のサイズを格納して、より多くの領域を割り当てる必要があります。

sizeof(*array)sizeofオペレータは、式のタイプを考慮して、ケース内の他の言葉で(*(int *))sizeof(int)と同じです。

C++では、ダイナミックアレイ内の要素の数を記憶させるこの作業は、標準クラスstd::vectorによって行われます。

x = realloc(x, ...);は、割り当てに失敗した場合にはNULLによってそのメモリがリークされるため、ポインタxが上書きされる可能性があることを覚えておいてください。

関連する問題