2012-04-04 6 views
0
gcc (GCC) 4.6.3 
c89 
apache runtime portable libraries 

Hallo,erklären Speicher malloc

Nur eine einfache Frage, die ich denke, ich versuche, einen UUID-Wert zu schaffen.

Ich möchte mich Funktion, die es erstellt, um allein zu sein (Black Box), so kann ich einfach einen Puffer übergeben und die Funktion wird den Rest tun.

Das bedeutet, ich muss Speicher auf dem Heap in dieser Funktion deklarieren, da die aufrufende Funktion nicht viel zu deklarieren weiß. Ich weiß, dass das eine schlechte Idee ist, da der Callie den Speicher freigeben muss, nachdem er damit fertig ist.

Gibt es eine Möglichkeit, dass ich das besser machen kann?

Wenn ich dies ausführe, ist die branch_id_buf immer Null, nachdem die Funktion zurückgibt. Ich habe es jedoch an die Funktion übergeben, so dass es nicht null sein sollte, wenn die Funktion zurückkehrt, da sie auf einen zugewiesenen Speicher verweisen sollte.

Vielen Dank für jede Beratung,

static void g_get_branch_id(char *branch_id_buf); 

int main(void) 
{ 
    char *branch_id_buf = NULL; 

    g_get_branch_id(branch_id_buf); 

    printf("branch id [ %s ]\n", branch_id_buf); 

    free(branch_id_buf); 

    return 0; 
} 

static void g_get_branch_id(char *branch_id_buf) 
{ 
    apr_uuid_t uuid; 

#define MAGIC_COOKIE_LENGTH 9 

    const char *MAGIC_COOKIE = "z9hG4bk-"; 
    const int BRANCH_ID_LENGTH = APR_UUID_FORMATTED_LENGTH + MAGIC_COOKIE_LENGTH; 

    branch_id_buf = malloc(BRANCH_ID_LENGTH); 
    if(branch_id_buf == NULL) { 
     return; 
    } 

    strncpy(branch_id_buf, MAGIC_COOKIE, BRANCH_ID_LENGTH); 
    printf("branch id [ %s ]\n", branch_id_buf); 
    apr_uuid_get(&uuid); 

#define PREFIX_BRANCH_LENGTH 8 
    apr_uuid_format(branch_id_buf + PREFIX_BRANCH_LENGTH, &uuid); 

    printf("branch id [ %s ]\n", branch_id_buf); 
} 
+0

malloc gibt NULL zurück, wenn Speicher nicht zugewiesen werden konnte. Sind Sie sicher, dass Ihnen beim Ausführen dieses Programms nicht die Ressourcen ausgehen? – fduff

+0

Was passiert, wenn Sie einen Schritt in g_get_branch_id() ausführen? – fduff

Antwort

1

Im Allgemeinen ist es eine sehr schlechte Idee, in einem Modul und frei in einem anderen zuzuordnen. Genau so erstellen Sie in Ihren Programmen zahlreiche Speicherlecks. Ihr Code ist besonders problematisch, da Sie nicht nur den Aufrufer frei lassen, sondern auch die Verantwortung, den Zeiger auf NULL zu initialisieren. Es scheint, dass Sie nur mit Kompilierzeitkonstanten (?) Arbeiten.), also verstehe ich nicht, warum du sogar malloc brauchst. Kannst du das nicht tun?

Die Array-Länge im Prototyp zeigt dem Aufrufer an, dass sie einen Zeiger auf einen Puffer mit dieser Länge übergeben sollten.

+0

Danke, das hat mir sehr geholfen. – ant2009

3

Im Code geschrieben ist branch_id_buf auf die Funktion local: alle Änderungen werden den Anrufer nicht sichtbar sein.

Sie benötigen ein char** weitergeben müssen:

char *branch_id_buf = NULL; 

g_get_branch_id(&branch_id_buf); 

... 

void g_get_branch_id(char **branch_id_buf) { 

    /* Dereference 'branch_id_buf' within this function. */ 
    *branch_id_buf = malloc(BRANCH_ID_LENGTH); 

EDIT:

Wie larsmans kommentiert, sollten Sie eine char* Rückkehr eher als ein Argument akzeptieren:

char *branch_id_buf = g_get_branch_id(); 

char* g_get_branch_id() { 

    char* branch_id_buf = malloc(BRANCH_ID_LENGTH); 
    ... 
    return branch_id_buf; 
} 
+1

Da die Funktion momentan 'void' zurückgibt, ist es eine viel bessere Idee, wenn sie ein 'char * 'an den zugewiesenen Speicher zurückgibt. –

+0

Danke, ich habe über den Zeiger auf den Zeiger nachgedacht. Aber vielleicht sah es einfach vorbei. – ant2009

+1

@larsmans, einverstanden. – hmjd

2

ist NICHT a schlechte Idee. Seien Sie vorsichtig und denken Sie daran, diese Erinnerung freizugeben. Es gibt einige gebräuchliche Techniken, um es noch sicherer zu machen. wie Referenzzähl- oder Release-Pools.

Alternativ können Sie Ihre "Black Box" zweimal anrufen. Erster Aufruf, um so viel Speicher zu machen, den Sie benötigen, und zweitens Aufruf mit Zeiger auf bereits zugewiesenen Puffer.

+0

Klingt wie eine gute Idee, aber eine Initialisierungsfunktion, um die komplette Größe zu bekommen, die ich brauche. – ant2009

+0

Da dies jedoch nur eine Funktion ist, müsste ich auch die Konstanten dort eingeben. Ich denke ich würde die Konstanten duplizieren. Etwas, an dem ich nicht interessiert bin. Und ich möchte sie nicht in eine Header-Datei einfügen. – ant2009

+0

Sie können sprintf aufrufen (NULL, "% d", 10000); Länge (-1) der Zeichenfolge lang genug, um "10000" zu speichern. Dies ist ein Beispiel für meinen zweiten Gedanken. – jacekmigacz