2015-04-15 19 views
10

Ho creato una funzione progettata per ottenere l'input dell'utente. Richiede che la memoria sia allocata alla variabile che contiene l'input dell'utente; tuttavia, tale variabile viene restituita alla fine della funzione. Qual è il metodo corretto per liberare la memoria allocata/restituire il valore della variabile?Modo corretto per liberare la memoria di una variabile restituita

Ecco il codice:

char *input = malloc(MAX_SIZE*sizeof(char*)); 
int i = 0; 
char c; 

while((c = getchar()) != '\n' && c != EOF) { 
    input[i++] = c; 
} 

return input; 

Devo restituire l'indirizzo di ingresso e liberarla dopo che è stato utilizzato?

Curioso come il metodo più appropriato per liberare la variabile di input.

+0

Se si 'malloc', alla fine qualcuno avrà bisogno di' free', sia che si tratti di un'altra API o del chiamante. Correlati, se supportati sulle piattaforme di destinazione, ['getline'] (http://pubs.opengroup.org/stage7tc1/functions/getdelim.html), una funzione di libreria aggiunta a POSIX.1-2008, sembrerebbe per * quasi * fare ciò che stai cercando di implementare. Richiede comunque al chiamante di "liberare" qualsiasi allocazione restituita, ma fornisce anche la semantica del riutilizzo, dove il codice * non *. A seconda dell'uso previsto e delle piattaforme di destinazione, può valere la pena di prendere in considerazione. – WhozCraig

risposta

11

È piuttosto semplice, se si passa a free() lo stesso puntatore restituito da malloc() va bene.

Per esempio

char *readInput(size_t size) 
{ 
    char *input; 
    int chr; 
    input = malloc(size + 1); 
    if (input == NULL) 
     return NULL; 
    while ((i < size) && ((chr = getchar()) != '\n') && (chr != EOF)) 
     input[i++] = chr; 
    input[size] = '\0'; /* nul terminate the array, so it can be a string */ 
    return input; 
} 

int main(void) 
    { 
    char *input; 
    input = readInput(100); 
    if (input == NULL) 
     return -1; 
    printf("input: %s\n", input); 
    /* now you can free it */ 
    free(input); 
    return 0; 
    } 

Cosa non si dovrebbe mai fare è qualcosa di simile a

free(input + n); 

perché input + n non è il ritorno puntatore malloc().

Ma il codice, ha altri problemi si dovrebbe prendere cura di

  1. si assegnano spazio per MAX_SIZEchar s così si dovrebbe moltiplicare per sizeof(char) che è 1, invece di sizeof(char *) che allocare MAX_SIZE puntatori, inoltre potresti rendere MAX_SIZE un parametro di funzione, perché se stai allocando un buffer fisso, puoi definire un array in main() con la dimensione MAX_SIZE come char input[MAX_SIZE] e passarlo a readInput() come parametro r, evitando così malloc() e free().

  2. Si sta allocando molto spazio ma non si impedisce l'overflow nel ciclo while, è necessario verificare che i < MAX_SIZE.

+0

Non può usare gli array locali, poiché quando ritorna e il frame dello stack della funzione viene distrutto, non ci sarà modo di garantire che l'array sia intatto. Il compilatore ti avviserà: "la funzione restituisce l'indirizzo della variabile locale [-Wreturn-local-addr]". A parte questo, buona risposta. –

+1

@EnzoFerber I significava passare l'array alla funzione e compilarlo lì, so che non è necessario restituire un array locale. Penso di aver bisogno di chiarirlo. –

4

Si potrebbe scrivere una funzione con tipo di ritorno char*, tornare input, e chiedere all'utente di chiamare free una volta la loro fatto con i dati.

Si potrebbe anche chiedere all'utente di inoltrare un buffer opportunamente dimensionato, insieme con un limite di dimensione del buffer, e restituire quanti caratteri sono stati scritti nel buffer.

-1

Questo è un caso classico. Una funzione mallocs memoria per il suo risultato, il chiamante deve liberare il valore restituito. Ora stai camminando sul ghiaccio sottile delle perdite di memoria c. 2 motivi

Primo; non c'è modo per voi di comunicare il requisito libero in un modo applicabile (cioè il compilatore o il runtime non possono aiutarvi - a differenza di specificare quali sono i tipi di argomento).Devi solo documentarlo da qualche parte e sperare che il chiamante abbia letto i tuoi documenti

Secondo: anche se il chiamante sa di liberare il risultato, potrebbe commettere un errore, viene eseguito un percorso di errore che non libera la memoria. Questo non causa un errore immediato, le cose sembrano funzionare, ma dopo aver funzionato per 3 settimane l'app si blocca dopo esaurimento di memoria

Ecco perché così tanti linguaggi 'moderni' si concentrano su questo argomento, C++ puntatori intelligenti, Java, C#, ecc. Garbage Collection, ...