2016-05-10 69 views
31

Mi chiedo il motivo per cui gli array statici non devono essere liberati? So che quando si crea un array dinamico, ad es.Perché gli array statici non devono essere liberati?

int *p; 
p = malloc(10*sizeof(int)); 

Dobbiamo liberare la memoria allocata utilizzando:

free(p); 

E per una matrice statica in una funzione, la matrice statica saranno liberati automaticamente quando viene eseguita la funzione chiamata.

Quello che non capisco è: quando si ritorna un array statico utilizzando una funzione come questa:

int *subFunc(){ 
    static int a[5] = {1,2,3,4,5}; 
    return a; 
} 

int main(){ 
    int *p; 
    p = subFunc(); 
} 

Se la matrice statica viene liberato automaticamente dopo aver completato l'esecuzione, allora come possiamo ancora accedere ai valori di la matrice statica correttamente?

risposta

42

Se la matrice statica viene automaticamente liberata dopo aver completato l'esecuzione, come è possibile accedere ai valori dell'array statico in modo corretto?

No, non è così. Le variabili static vengono inizializzate prima di iniziare main() e la sua durata è l'intera esecuzione del programma. Quindi, possono essere return e dalle funzioni (in cui sono definiti) e possono ancora essere accessibili. Non sono locali (alle funzioni) che si esauriscono quando la funzione termina l'esecuzione.

correlati, citando C11, capitolo §6.2.4

Un oggetto cui identificatore è dichiarato senza la classe di archiviazione specificatore _Thread_local, e sia con collegamento esterno o interno o con la classe di archiviazione specificatore static, ha durata di archiviazione statica. La sua durata è l'intera esecuzione del programma e il suo valore memorizzato viene inizializzato solo una volta, prima dell'avvio del programma.

Per quanto riguarda il campo di applicazione di una variabile static all'interno di una funzione, sì, è limitata alla funzione stessa, come accennato nel capitolo §6.2.1,

[...] Se il dichiaratore o identificatore del tipo che dichiara che l'identificatore appare all'interno di un blocco o all'interno dell'elenco delle dichiarazioni dei parametri in una definizione di funzione, l'identificatore ha ambito di blocco, che termina alla fine del blocco associato . [...]

Ciò significa, ovviamente, non è possibile utilizzare la matrice a fuori subFunc(), come a non è visibile fuori subFunc().

Tuttavia, quando si utilizza l'array return (la restituzione di un array causa il decadimento del puntatore al primo elemento dell'array, FWIW), poiché la durata dell'array static è l'intera esecuzione del programma, con l'accesso al reso puntatore (sicuramente, entro limiti) è perfettamente valido e legale.

+5

'locali static' si comportano in modo leggermente diverso da' globali static': essi non sono inizializzate all'avvio del programma, ma [quando l'esecuzione passa dapprima loro punto inizializzazione] (http://stackoverflow.com/questions/ 246564/what-is-the-vita-di-un-statico-variabile-in-ac-funzione). – Quentin

+4

@Quentin Sei sicuro che sia così anche per C? Puoi collegare qualche riferimento? –

+2

Apparentemente ho mescolato effettivamente le regole C e C++. Colpa mia ! – Quentin

20

Le variabili statiche continuano ad esistere anche dopo che il blocco in cui sono definiti termina. Pertanto, il valore di una variabile statica in una funzione viene mantenuto tra chiamate con funzioni ripetute alla stessa funzione . L'ambito delle variabili automatiche statiche è identico a quello di variabili automatiche, cioè è locale al blocco in cui è definito ; tuttavia, la memoria allocata diventa permanente per la durata del programma. Le variabili statiche possono essere inizializzate nelle loro dichiarazioni ; tuttavia, gli inizializzatori devono essere espressioni costanti, e l'inizializzazione viene eseguita una sola volta in fase di compilazione quando la memoria è allocata per la variabile statica. - source

La matrice o le variabili statiche non vengono liberate quando il controllo esce da tale funzione. L'ambito della variabile statica è locale rispetto alla funzione in cui è stato dichiarato, ma la sua durata è in tutto il programma.

+1

Proprio oggi ho sentito qualcuno dire "non importa se si trova all'interno di una funzione, * una variabile statica è per sempre *". – Agostino

+2

@Agostino Ovviamente, poiché non tutte le variabili statiche vengono distrutte contemporaneamente, è chiaro che alcune di esse godono di valori maggiori di _forever_ rispetto ad altri. :-) –

10

E per una matrice statica in una funzione secondaria, la matrice statica saranno liberati automaticamente quando viene eseguita la funzione chiamata sub.

Questo non è vero. Gli array statici non vengono creati quando si inserisce la funzione e non vengono distrutti quando lo si lascia.

Una variabile statica, ei dati al suo interno, sono in realtà molto simili a una variabile globale! L'unica cosa locale alla funzione è il nome. (Sentirai parlare della "portata" della variabile - questo significa "dove posso usare il nome per fare riferimento ad esso.")

Quindi, quando stai pensando alla vita di un array statico, è possibile sostituire mentalmente:

int *subFunc(){ 
    static int a[5] = {1,2,3,4,5}; 
    return a; 
} 

con

int ONLY_USE_ME_INSIDE_SUBFUNC__a[5] = {1,2,3,4,5}; /* global variable */ 

int *subFunc(){ 
    int * a = ONLY_USE_ME_INSIDE_SUBFUNC__a; /* a is the same as the global */ 
    return a; 
} 

e poi far finta di nessun altro nel programma può toccare quella variabile globale.

+0

Per inciso, alcuni compilatori considereranno il primo come quest'ultimo, ma usando un nome generato automaticamente come '$ STATIC $ fd91a2e7 $ subFunc_a' che può essere garantito non in conflitto con tutto ciò che sarebbe valido in un file C [ poiché gli identificatori utente non possono contenere segni del dollaro]. – supercat

2

Static variables all'interno di una funzione, in genere utilizzato per mantenere alcuni dati in un ambito della funzione su più chiamate per esso. Sono inizializzati prima di main() e la loro durata è come l'intera esecuzione del programma. Quindi, non avrebbe senso se fossero stati liberati dopo l'uscita dalla funzione. Se li si libera, si bloccheranno la prossima volta che si chiama la funzione perché non saranno referenziati.

3

Mi chiedo perché gli array statici non debbano essere liberati?

  1. Qualsiasi non viene assegnato da una funzione di gestione della memoria (malloc, calloc), come int a[5] non è necessario esplicitamente essere curati per liberare .

  2. Le variabili statiche, ad esempio static int a[5], devono essere accessibili nell'ambito locale (mantengono i loro valori tra chiamate successive della funzione locale). Vengono creati al momento della compilazione esattamente per questo scopo, hanno una durata del programma, quindi non sarebbe una considerazione logica liberarli, anche se fosse possibile, che non è.

  3. Tutto il resto viene spiegato magistralmente in altre risposte.