2010-02-28 14 views
5

mia funzione:in C: Perché una struttura allocata nello stack esiste al di fuori della funzione?

struct hostent * gethost(char * hostname){ 
    if(/*some condition under which I want 
     to change the mode of my program to not take a host*/){ 
     return null 
    } 
    else{ 
     struct hostent * host = gethostbyname(hostname); 
     return host; 
    } 
} 

nel principale:

struct hostent * host = gethost(argv[2]); 

(ignorare eventuali piccoli errori nel codice, sto vomitando da memoria)

questo funziona bene. e Valgrind non mi dice che sto perdendo memoria, nonostante il fatto che non mi stia liberando.

Perché? Ho pensato che le cose allocate nello stack sparissero con la chiamata alla funzione che ritornava? o è perché restituisco il puntatore? è pericoloso in qualche modo?

risposta

10

host non è allocato nello stack, solo un puntatore ad esso è in pila. Il puntatore viene copiato quando la funzione ritorna, quindi non c'è nulla di sbagliato nel codice.

Si noti che gethostbyname in realtà non allocare dinamicamente memoria. Restituisce sempre un puntatore allo stesso blocco di memoria assegnato in modo statico, motivo per cui valgrind non segnala una perdita. Fai attenzione, però, perché ciò significa che devi copiare lo hostent restituito dalla funzione se desideri salvare il valore per dopo, poiché ulteriori chiamate a gethost la sovrascriveranno.

+0

Ah grazie mille. Quindi è unico per 'gethostbyname'? se l'ho fatto per un 'char *', ad esempio, i valori in quell'array potrebbero essere sovrascritti in seguito? Il mio programma deve gestire solo un host per corsa, quindi dovrebbe andare bene. –

+0

Se il valore indicato da un puntatore viene sovrascritto nelle chiamate successive dipende dalla funzione che si sta chiamando. Per qualsiasi funzione di libreria standard C che restituisce un puntatore che non si passa, si può presumere che restituisca un puntatore alla memoria statica e che possa essere sovrascritto. – Gabe

0

Bene, la memoria non è trapelata fino a quando non vengono persi tutti i riferimenti a esso, nell'esempio il puntatore viene restituito in modo che vi sia ancora un riferimento ad esso.

Tuttavia, imho è una pessima decisione di progettazione nella maggior parte dei casi affidarsi a un'altra parte del codice per rilasciare memoria dinamica. Se la funzione deve restituire una struttura, ad esempio, il chiamante dovrebbe farlo e passare un puntatore alla struttura.

+2

La memoria non è trapelata perché 'gethostbyname' non esegue l'allocazione dinamica. Restituisce un puntatore statico ogni volta. – Gabe

+2

E chi, prega tell, tiene traccia dei riferimenti su questo puntatore?:) – vladr

+2

Nessuno traccia i riferimenti al puntatore. Il blocco di memoria viene assegnato quando la libreria socket viene caricato e non viene deallocato fino a quando il processo non termina o la libreria socket viene scaricata. – Gabe

2

dal manuale:

RETURN VALUE 
     The gethostbyname() and gethostbyaddr() functions return the hostent 
     structure or a NULL pointer if an error occurs. On error, the h_errno 
     variable holds an error number. When non-NULL, the return value may 
     point at static data, ... 

Alcuni memoria è riservata al momento della compilazione (cioè all'interno del binario codice.) Per la struttura, la funzione restituisce un puntatore a questa memoria.

3

Va bene e perde perché il puntatore restituito non punta ai dati su stack o heap, ma alcune variabili statiche.

http://linux.die.net/man/3/gethostbyname:

gethostbyname funzioni() e gethostbyaddr() può restituire puntatori ai dati statici, che possono essere sovrascritti da chiamate dopo. Copiare la struct hostent non è sufficiente, poiché contiene puntatori; è necessaria una copia profonda.

+0

Perché "globale"? Globali e statici non sono la stessa cosa – Ben

Problemi correlati