2009-08-20 11 views
10

So che dovremmo liberare qualsiasi variabile allocata con malloc, ma se torno in una funzione assegnata? Qualcosa di simile:Restituisce una variabile

char *somefunction(int somearg){ 
    char *str; 

    str=(char *)malloc(sizeof(char *)); 

    //some code 

    return str; 
} 

Devo liberare str? Come potrei farlo?

+2

L'argomento di 'malloc()' è quasi certamente sbagliato - stai allocando abbastanza memoria per memorizzare un 'char *', ma assegnando a un puntatore che punta a 'char' (e non è necessario eseguire il ritorno valore di 'malloc' in C, entrambi). 'str = malloc (N * sizeof * str);' è un modo migliore per scriverlo. – caf

+0

Come detto da CAF, non si dovrebbe mai trasmettere il valore di ritorno di malloc(). Vedere http://stackoverflow.com/questions/1565496/specifically-whats-dangerous-about-casting-the-result-of-malloc et al – Mawg

risposta

13

Si hanno due opzioni: una, passare un carattere * a una funzione e utilizzare quella invece di allocare all'interno di una funzione, o due, liberare il valore restituito in seguito.

La prima opzione:

char *somefunction(char *str, int somearg){ 

    //some code 

    return str; 
} 

// Elsewhere... 
char *str = (char *) malloc....; 
somefunction(str, 123); 
// Code... 
free(str); 

La seconda opzione:

char *somestr = somefunction(123); 
// Do something... 
free(somestr); 

io personalmente suggerisco la prima opzione, in quanto è un po 'più facile per evitare che la memoria che perde quando non viene assegnato all'interno di funzioni arbitrari .

+1

Buona risposta (e domanda), sono incappato nello stesso problema da poco. Una domanda: cosa succede se è difficile determinare in anticipo la quantità di memoria necessaria per il valore di ritorno della funzione? Allora sembrerebbe più naturale allocare nella funzione; in caso contrario, è necessario un po 'di gestione degli errori nella funzione, nel caso in cui lo spazio di memoria fornito sia troppo piccolo (ad esempio per restituire una stringa di lunghezza variabile). – sleske

+0

Una stringa di lunghezza variabile potrebbe giustificare l'assegnazione di memoria all'interno della funzione. Sarei molto titubante circa tale codice nel mio progetto però, e piuttosto preferisce specificare esplicitamente una lunghezza massima che viene scelto in base al contesto e requisiti del codice. Di che tipo di stringhe di lunghezza variabile stai parlando? Non potrebbero essere più di diversi KB/MB che potrebbero essere pre-assegnati? –

2

È necessario liberare tutto lo spazio allocato, ma se si restituisce perché si utilizzerà lo spazio di memoria in altre parti del programma, quindi dopo averlo utilizzato è necessario liberare. Visualizza ogni posizione nel codice che chiama la funzione e libera lo spazio dopo aver utilizzato il valore restituito.

2

Se si desidera restituire l'indirizzo del blocco, non si dovrebbe liberare() il blocco, ma invece fare affidamento sul codice chiamante per liberarlo() in un secondo momento. Questo è chiamato passaggio di onwership.

Se lo si libera nella funzione e si restituisce il puntatore, il codice chiamante verrà eseguito in un comportamento non definito che tenta di accedere al blocco già liberato.

4

liberi quando hai finito con esso. Non esiste una regola che dice che il free() che corrisponde a un malloc() deve avere la stessa funzione.

+0

così, avrei potuto fare qualcosa di simile gratuito (str) dalla funzione o libero (someFunction)? –

+1

Sì, certo. Proprio come si può fare con malloc(), che dopotutto è solo un'altra funzione. –

2

Questa è una pratica per alcune funzioni esistenti (strdup(), ad esempio) ma è generalmente una cattiva idea. Richiedere all'utente di essere a conoscenza di ciò che accade all'interno di una chiamata di funzione è una cattiva esigenza: pensa a quante funzioni usi chi è interno a te nascosto. In generale, si vuole avere un pass utente in un buffer e le dimensioni, invece di allocazione di memoria per loro.

+1

Concordato, ma cosa succede se è difficile decidere in anticipo quanto spazio sarà necessario (ad esempio, creare dinamicamente una stringa da restituire). Quindi sembrerebbe più naturale (e più semplice) per la funzione allocare tutta la memoria di cui ha bisogno. Cosa ne pensi? – sleske

+0

Un ottimo punto. Tuttavia, in realtà, ci sarà sempre una lunghezza massima nota per la puntura, in quanto dovrà inserirsi in un campo del database, o su uno schermo o un output formattato. Ovviamente, è inutile allocare 255 byte quando potrebbe essere necessario solo uno, quindi dipende da cosa si sta implementando. Non mi preoccuperei troppo di un'applicazione Windows, ma un sistema embedded su un micro 8 bit è un diverso bollitore di cavalli colorati. – Mawg

Problemi correlati