2013-03-29 19 views
5

Begann zu lernen malloc.h in C. Die Idee war, dynamische Array zu erstellen. Hier ist der Code:Was ist los mit 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; 
} 

Das Ergebnis ist

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 

Jedes Mal, >=8 Werte zufällig sind. Ich habe keine Ahnung, warum es passiert, also was ist los?

+1

Was passiert, wenn Sie mit einem Debugger Schritt für Schritt durch Ihren Code gehen? – SecurityMatt

+8

Sie sollten lernen, wie 'sizeof()' zuerst funktioniert. –

+1

Hinweis: Was ist der Datentyp von '* array'? 'array' ist ein Zeiger auf int. –

Antwort

7

Sie undefined Verhalten in Ihrem Code. Ich nehme an, dies zu tun:

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

Sie erwarten, dass sizeof(*array) kehren Sie die Größe des gesamten Arrays, nicht wahr? Das stimmt aber nicht. sizeof wird zur Kompilierzeit berechnet, und sizeof(*array) ist tatsächlich das gleiche wie sizeof(int).

Also, um dieses Array erweiterbar zu machen, müssen Sie zusätzliche Variable haben, die aktuelle Anzahl der Elemente halten und so etwas wie:

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

wo current_size_of_array auf jeder Schleife der for erhöht werden, wenn Sie fügen tatsächlich ein weiteres Element hinzu.

+0

yeah, du hast vollkommen recht. aber ich habe gerade meinen Code mit einem anderen Compiler gecheckt und es funktioniert! es ist komisch ... wie auch immer, thats für Erklärung! – ovnia

+1

@wingsofovnia - es funktioniert genau, weil es _undefined Behavior_ ist und dies bedeutet, dass alles passieren kann. –

3

sizeof(*array) tut nicht sagen Ihnen, wie groß das Array ist. Es teilt Ihnen mit, wie viele Bytes ein int belegt. Daher weist jeder Aufruf von realloc nur Speicher für zwei int-Werte zu. Ändern Sie den realloc Aufruf, um sizeof(int) mal die Anzahl der gewünschten Ints zuzuweisen.

2

sizeof(int)+sizeof(*array)

Denken Sie, dass sizeof(*array) die Anzahl der Bytes ist bereits vergeben. Sie haben Unrecht, sizeof(*array) ist die Größe von einem int. Du überholst also deinen Puffer, und das verursacht schließlich ein Problem.

Bevor Sie fragen, gibt es keinen Standard Weg, um die Größe bereits zugewiesen zu bekommen. Normalerweise müssen Sie es für sich selbst speichern (oder in C++ verwenden Sie etwas mit einer benutzerfreundlicheren Schnittstelle als malloc, wie vector). In diesem Fall benötigen Sie die vorhandene Größe nicht, Sie können die neue erforderliche Größe aus i erarbeiten.

1

Die Größe eines von malloc zugewiesenen Speicherblocks ist der Bibliothek bekannt (free benötigt nur den Zeiger), aber es gibt keinen tragbaren Weg, diese Nummer zurück zu bekommen. Sie müssen in einer anderen Variablen die aktuelle Größe speichern, damit Sie mehr Speicherplatz zuweisen können.

In sizeof(*array) der sizeof Betreiber berücksichtigt nur die Typ des Ausdrucks und in Ihrem Fall ist (*(int *)) mit anderen Worten ist die gleiche wie sizeof(int).

In C++ wird diese Aufgabe, die Anzahl der Elemente in einem dynamischen Array zu speichern und die Größe zu erhöhen, von der Standardklasse std::vector übernommen.bitte

Als Randbemerkung vergessen, dass x = realloc(x, ...); eine schlechte Idiom ist, weil bei Zuordnungsfehler des Zeiger x durch NULL, dass der Speicher undicht überschrieben würde.