2016-03-31 7 views
1

Ich habe die struct foo wie folgt erklärt:Wie können Heap-Objekte Daten vom Stack verwenden?

struct foo { 
    const char* name_lower; 
    const char* name_caps 
    //.. 
}; 

ich dynamisch Instanzen foo auf dem Heap erstellen und einen Wert in der name_lower und name_caps Membervariable speichern möchten. Dies wird durch die Funktion getan bar

void bar(foo* entry, const char* str, int delimiter_pos) { 

    char l[2] = {str[caps_pos-1], '\0'}; // create new string 
    char c[2] = {str[caps_pos+1], '\0'}; 

    entry->name_lower = &l[0]; // assign these strings the foo instance 
    entry->name_caps = &c[0]; 
} 

Ich mache mir Sorgen, weil ich weiß nicht, ob dieser Code zum Absturz bringen wird. Die temporär erstellten Arrays l und c werden auf dem Stack gespeichert. Sobald die Funktion beendet ist, wird der Stapel gelöscht und c und l werden wahrscheinlich verschwinden.

Bedeutet dies, dass die foo Instanz ihre Namen verliert, d. H. Ihre Referenzen? Wenn ja, wie kann ich dieses Problem lösen?

+0

Google für "dynamische Speicherzuweisung" - http://www.programiz.com/c-programming/c-dynamic-memory-allocation –

+0

Ich kenne die Prinzipien zur dynamischen Speicherzuweisung. Bedeutet das, dass ich l und c auf dem Haufen speichern muss, indem ich malloc anrufe? – null

+0

Ja, genau. andernfalls werden sie auf die Adresse zeigen, die undefinierte Werte enthalten, nachdem der Ablauf von "bar" zurückkehrt. –

Antwort

0

Sie sollten stattdessen char *l = (char *)malloc(2 * sizeof(char)); verwenden und dann initialisieren; ähnlich für char *c. Dann setzen entry->name_lower = l; entry->name_caps = c;

Bei der Zuweisung sicherstellen, dass Sie überprüfen, ob die Zuweisung erfolgreich war, d. H. Ob malloc nicht-NULL-Adresse zurückgegeben.

Stellen Sie sicher, dass Sie den Speicher freigeben, nachdem Sie ihn nicht mehr benötigen: free(entry->name_lower); free(entry->name_caps);.

0

Es wird nicht verlieren nichts. Die Zeiger in der struct behalten ihren Wert, aber der Inhalt wird sich ändern und Sie werden schließlich SIGSEGV bekommen.

Damit die char * beibehalten wird, müssen Sie sie auch auf dem Heap zuweisen.

void bar(foo* entry, const char* str, int delimiter_pos) { 
    char * l = malloc(2); 
    char * c = malloc(2); 
    /* Check l and c for NULLs */ 

    l[0] = str[caps_pos-1]; 
    l[1] = '\0'; 
    c[0] = str[caps_pos+1]; 
    c[1] = '\0'; 

    entry->name_lower = l; 
    entry->name_caps = c; 
} 

Denken Sie daran, dass Sie sollten auch free() die Strukturkomponenten, wenn Sie nicht mehr benötigen.

1

aus dem Kommentar Fortsetzung, ist der einfachste Weg, um die Startadresse für neue Speicherblocks für l und c zuzuteilen/kopieren und ordnen ist strdup zu verwenden (von string.h):

void bar(foo* entry, const char* str, int delimiter_pos) { 

    char l[2] = {str[caps_pos-1], '\0'}; // create new string 
    char c[2] = {str[caps_pos+1], '\0'}; 

    entry->name_lower = strdup (l); // assign these strings the foo instance 
    entry->name_caps = strdup (c); 
} 

Nicht vergessen zu free der Speicher zugeordnet entry->name_lower und entry->name_caps, wenn nicht mehr benötigt.

0

Wenn die Länge Ihrer Zeichenfolgen begrenzt ist, können Sie char Arrays anstelle von Zeigern verwenden. In Ihrem Beispiel haben alle Saiten eine Länge von 1 Saiten Unter der Annahme, nicht länger sein kann als das, Sie char[2] statt char* verwenden:

struct foo { 
    char name_lower[2]; 
    char name_caps[2]; 
    //.. 
}; 

void bar(foo* entry, const char* str, int delimiter_pos) { 
    entry->name_lower[0] = str[caps_pos-1]; 
    entry->name_lower[1] = '\0'; 
    entry->name_caps[0] = str[caps_pos+1]; 
    entry->name_caps[1] = '\0'; 
} 

Historische Anmerkung:

Weil dies so einfach zu bedienen sind Die Leute haben sich daran gewöhnt und künstliche Begrenzungen der Stringlänge erzwungen, was zu Pufferüberläufen führte. Wenn Ihre Zeichenfolgen nicht begrenzt sind, verwenden Sie die dynamische Zuweisung anstelle von char Arrays.

Verwandte Themen