Frage

Jemand hier zeigte kürzlich in einem Stück Code von mir zu mir ich bin mit

char* name = malloc(256*sizeof(char));
// more code
free(name);

war ich unter dem Eindruck, dass auf diese Weise eine Reihe von Einrichtung war identisch mit mit

char name[256];

und dass beiden Wege würden die Verwendung von freien require (). Bin ich falsch, und wenn ja könnte jemand bitte erklären, in geringen Worten, was ist der Unterschied?

War es hilfreich?

Lösung

Im ersten Code wird der Speicher auf dem Heap dynamisch zugewiesen. Diese Erinnerung muss mit freiem befreit (). Seine Lebensdauer ist beliebig. Es Funktion Grenzen überschreiten kann, etc

In dem zweiten Code wird das 256 Bytes auf dem Stapel zugeordnet und werden automatisch freigegeben, wenn die Funktion zurückkehrt (oder bei Programmende, wenn es außerhalb aller Funktionen). Sie müssen also nicht (und kann) nennen free () auf sie. Es kann nicht auslaufen, aber es wird auch nicht über das Ende der Funktion lebt.

Wählen Sie zwischen den beiden auf der Grundlage der Anforderungen für den Speicher.

Addendum (Pax):

Wenn ich diese hinzufügen, Ned, werden die meisten Implementierungen bieten in der Regel mehr als Haufen Stapel (zumindest in der Standardeinstellung). Dies wird normalerweise nicht für 256 Byte Rolle, es sei denn, Sie sind bereits aus Stapel laufen oder stark rekursive Sachen zu tun.

Auch sizeof (char) ist immer 1 nach der Norm, so dass Sie nicht, dass überflüssige multiplizieren müssen. Auch wenn die Compiler wahrscheinlich weg optimieren, macht es den Code hässlich IMNSHO.

Ende Addendum (Pax).

Andere Tipps

  

und dass beiden Wege würden die Verwendung von freien require ().

Nein, nur die erste benötigt die Verwendung eines frei. Das zweite ist, auf den Stapel zugeordnet. Das macht es unglaublich schnell zuzuordnen. Schau mal hier:

void doit() {
    /* ... */
    /* SP += 10 * sizeof(int) */
    int a[10];
    /* ... (using a) */

} /* SP -= 10 */

Wenn Sie es schaffen, der Compiler bei der Kompilierung kennt seine Größe und die richtige Größe auf dem Stapel für sie zuordnen. Der Stack ist ein großer Teil der kontinuierlichen Speicher irgendwo befindet. etwas in den Stapel Putting inkrementiert nur (oder Abnahme je nach Plattform), um die Stackpointer. out of scope Going tun das Gegenteil, und das Array befreit wird. Das wird automatisch geschehen. Hierfür werden Variablen auf diese Weise erstellt haben automatische Speicherdauer.

malloc ist anders. Es wird einige beliebig große Speicher chunk bestellen (von einem Ort namens Frees ). Die Laufzeit wird einen ziemlich großen Speicherblock zum Nachschlagen. Die Größe kann zur Laufzeit bestimmt werden, so dass der Compiler im Allgemeinen es bei der Kompilierung nicht optimieren können. Da der Zeiger den Gültigkeitsbereich verlassen kann, oder um kopiert wird, gibt es keine inhärente Kopplung zwischen dem Speicher zugewiesen, und der Zeiger auf das die Speicheradresse zugeordnet ist, so wird der Speicher noch zugewiesen, auch wenn Sie die Funktion lange verlassen haben vor . Sie haben manuell frei übergeben Sie die Adresse, die Sie bekam von malloc zu nennen, wenn die Zeit dazu gekommen ist.

Einige „aktuelle“ Form C, genannt C99, können Sie Arrays mit einer Laufzeit Größe geben. D.h Sie tun dürfen:

void doit(int n) {
    int a[n]; // allocate n * sizeof(int) size on the stack */
}

Aber das Feature sollte besser vermieden werden, wenn Sie es nicht einen Grund haben zu verwenden. Ein Grund dafür ist, dass es nicht ausfallsicher ist: Wenn kein Speicher mehr verfügbar ist, kann alles passieren. Ein weiterer Grund ist, dass C99 nicht sehr portabel unter Compiler ist.

Es gibt eine dritte Möglichkeit hier, das ist, dass das Array kann auf eine Funktion extern deklariert werden, aber statisch, zB

// file foo.c
char name[256];

int foo() {
    // do something here.
}

Ich war ziemlich überrascht, in Antwort auf eine andere Frage auf, so dass jemand fühlte dies in C ungeeignet war; hier ist es nicht einmal erwähnt, und ich bin ein wenig verwirrt und überrascht (wie „was sie in diesen Tagen Kinder in der Schule unterrichten?“) darüber.

Wenn Sie diese Definition verwenden, wird der Speicher statisch zugewiesen, weder auf dem Heap noch den Stapel, sondern im Datenraum im Bild. So ist weder als mit malloc / free verwaltet werden müssen, noch müssen Sie sich Sorgen über die Adresse wiederverwendet werden wie bei einem Auto-Definition.

Es ist sinnvoll, die ganzen „erklärt“ vs „definiert“, was hier zu erinnern. Hier ist ein Beispiel

/* example.c */

char buf1[256] ;           /* declared extern, defined in data space */
static char buf2[256] ;    /* declared static, defined in data space */
char * buf3 ;              /* declared extern, defined one ptr in data space */
int example(int c) {       /* c declared here, defined on stack */
    char buf4[256] ;       /* declared here, defined on stack   */
    char * buf5 = malloc(256)]   /* pointer declared here, defined on stack */
                           /* and buf4 is address of 256 bytes alloc'd on heap */
    buf3 = malloc(256);    /* now buf3 contains address of 256 more bytes on heap */

    return 0;              /* stack unwound; buf4 and buf5 lost.      */
                           /* NOTICE buf4 memory on heap still allocated */
                           /* so this leaks 256 bytes of memory */
}

Nun in einer ganz anderen Datei

/* example2.c */

extern char buf1[];             /* gets the SAME chunk of memory as from example.c */
static char buf2[256];          /* DIFFERENT 256 char buffer than example.c */
extern char * buf3 ;            /* Same pointer as from example.c */
void undoes() {
     free(buf3);                /* this will work as long as example() called first */
     return ;
}

Das ist falsch - die Array-Deklaration keine freie erfordern. Ferner kann, wenn diese innerhalb einer Funktion ist, ist es auf dem Stapel zugeordnet ist (wenn der Speicher dient) und wird automatisch mit der Funktion zurückkehrt freigegeben - nicht einen Verweis auf sie passieren den Anrufer zurück

Überwinden Sie Ihre Aussage

char* name = malloc(256*sizeof(char)); // one statement
char *name; // Step 1 declare pointer to character
name = malloc(256*sizeof(char)); // assign address to pointer of memory from heap
name[2]; // access 3rd item in array
*(name+2); // access 3rd item in array
name++; // move name to item 1

Übersetzung: Name ist nun ein Zeiger auf Zeichen, die die Adresse einiger Speicher auf dem Heap zugewiesen

char name[256]; // declare an array on the stack
name++; // error name is a constant pointer
*(name+2); // access 3rd item in array
name[2]; // access 3rd item in array
char *p = name;
p[2]; // access 3rd item in array
*(p+2); // access 3rd item in array
p++; // move p to item 1
p[0]; // item 1 in array

Die Übersetzung: Name ist ein konstanter Zeiger auf ein Zeichen, das auf dem Stapel zu einem gewissen Speicherpunkten

In C-Arrays und Zeiger sind die gleiche Sache mehr oder weniger. Arrays sind konstante Zeiger auf Speicher. Der wesentliche Unterschied besteht darin, dass, wenn Sie malloc rufen Sie nehmen Ihr Gedächtnis aus dem Haufen und jeder Speicher aus dem Heap entnommen wird, muß aus dem Haufen befreit werden. Wenn Sie das Array mit einer Größe deklarieren wird Speicher aus dem Stapel zugewiesen. Sie können diesen Speicher frei, weil auf freie Speicher aus dem Heap gemacht wird. Der Speicher auf dem Stapel wird automatisch freigegeben werden, wenn die aktuelle Programmeinheit zurückgibt. Im zweiten Beispiel würde freie (P) auch einen Fehler sein. p ist ein Zeiger-Array der Name auf den Stapel. Also von p befreien Sie versuchen, den Speicher auf dem Stapel zu befreien.

Das ist nicht anders aus:

int n = 10;
int *p = &n;

Befreiung p in diesem Fall wäre ein Fehler, weil p Punkte n sein, die eine Variable auf dem Stapel befindet. Daher p einen Speicherplatz in dem Stapel hält und nicht befreit werden kann.

int *p = (int *) malloc(sizeof(int));
*p = 10;
free(p);

in diesem Fall die freien weil p Punkte auf einen Speicherplatz auf dem Heap korrekt ist, die von malloc zugeordnet wurde.

Je nachdem, wo Sie diese einsetzen, Stapelspeicher an einer riesigen Prämie sein könnte. Wenn zum Beispiel, sind Sie BREW-Code für Verizon / Alltel Handys zu schreiben, werden Sie in der Regel auf miniscule Stapel beschränkt, sondern haben immer Heap Zugang zu erhöhen.

Auch als char [] wird am häufigsten für Strings verwendet, ist es keine schlechte Idee, dem Zeichenfolge Konstruktion Methode zu ermöglichen, den Speicher braucht es für die Zeichenfolge in Frage zu vergeben, anstatt zu hoffen, dass immer und immer 256 (bzw. was auch immer Nummer Dekret) genügt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top