2011-01-28 8 views
31
#include <stdio.h> 

int foo1(void) 
{ 
    int p; 
    p = 99; 
    return p; 
} 

char *foo2(void) 
{ 
    char buffer[] = "test_123"; 
    return buffer; 
} 

int *foo3(void) 
{ 
    int t[3] = {1,2,3}; 
    return t; 
} 

int main(void) 
{ 
    int *p; 
    char *s; 

    printf("foo1: %d\n", foo1()); 
    printf("foo2: %s\n", foo2()); 
    printf("foo3: %d, %d, %d\n", p[0], p[1], p[2]); 
    return 0; 
} 

Quando compilo questo con gcc -ansi -pedantic -W -Wall i problemi del compilatore di avviso messaggi per foo2() e foo3():restituendo una variabile locale da funzioni in C

warning: function returns address of local variable 

ho pensato che non è permesso di restituire un variabile locale, ma foo1() funziona bene e sembra che ci sia un'enorme differenza tra restituire il puntatore a un oggetto locale e l'oggetto stesso.

Qualcuno potrebbe far luce su questo problema? Grazie in anticipo!

risposta

21

Il problema qui è che quando si crea la variabile locale viene allocata nello stack e quindi non è disponibile una volta che la funzione termina l'esecuzione (l'implementazione varia qui). Il modo preferibile sarebbe utilizzare malloc() per riservare memoria non locale. il pericolo qui è che devi deallocare (free()) tutto ciò che hai assegnato usando malloc(), e se si dimentica, si crea una perdita di memoria.

+0

Un altro pericolo è che se non si reimposta (ad esempio 'memset') la memoria allocata, questa potrebbe perdere informazioni dalla pila. – jweyrich

5

Qualsiasi variabile ha un po 'di spazio nella memoria. Un puntatore fa riferimento a quello spazio. Lo spazio occupato dalle variabili locali viene deallocato quando ritorna la chiamata alla funzione, il che significa che può essere e verrà riutilizzato per altre cose. Di conseguenza, i riferimenti a quello spazio finiranno per indicare qualcosa di completamente non correlato. Le matrici in C sono implementate come puntatori, quindi questo si applica a loro. E gli array costanti dichiarati in una funzione valgono anche come locali.

Se si desidera utilizzare un array o un altro puntatore oltre l'ambito della funzione in cui è stato creato, è necessario utilizzare malloc per riservare lo spazio per esso. Lo spazio prenotato usando malloc non verrà riallocato o riutilizzato finché non verrà rilasciato esplicitamente chiamando gratuitamente.

+2

+1. In pratica ciò significa che è necessario allocare un valore di ritorno sull'heap piuttosto sullo stack. È necessario utilizzare malloc o similair sugli "array" che si desidera restituire. O meglio, prendi un puntatore su un buffer + una lunghezza del buffer come parametri. – stefan

+0

@stefan: Sì, è un buon punto. Ho aggiunto altri suggerimenti su come risolvere questo alla risposta. –

+1

'Le matrici in C sono implementate come puntatori' è un'eccessiva semplificazione; è accettabile dal punto di vista del contesto, ma esistono grosse differenze tra gli array e i puntatori (oltre a molte somiglianze). –

15

Per foo1(), si restituisce un copia della variabile locale, non la variabile locale stessa.

Per le altre funzioni, si restituisce una copia di un puntatore a una variabile locale. Tuttavia, tale variabile locale viene deallocata al termine della funzione, quindi si finisce con brutti problemi se si tenta di fare riferimento in seguito.

0

Sì, si sta restituendo un array, che in realtà è un puntatore dietro le quinte, all'indirizzo della posizione di memoria in cui è memorizzato il contenuto della variabile inizializzata. Quindi ti avverte che potrebbe non essere altrettanto utile restituire un risultato del genere, quando invece potresti davvero voler dire uno dei valori dell'array.

Problemi correlati