web-dev-qa-db-fra.com

Pourquoi les tableaux statiques n'ont-ils pas besoin d'être libérés?

Je me demande pourquoi les tableaux statiques n'ont pas besoin d'être libérés? Je sais que lors de la création d'un tableau dynamique, par exemple.

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

nous devons libérer la mémoire allouée en utilisant:

free(p);

Et pour un tableau statique dans une fonction, le tableau statique sera automatiquement libéré lorsque la fonction appelée sera terminée.

Ce que je ne comprends pas, c'est: lors du retour d'un tableau statique à l'aide d'une fonction comme celle-ci:

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

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

Si le tableau statique est automatiquement libéré une fois l'exécution terminée, comment pouvons-nous toujours accéder correctement aux valeurs du tableau statique?

31
bienle

Si le tableau statique est automatiquement libéré après avoir terminé l'exécution, alors comment pouvons-nous toujours accéder correctement aux valeurs du tableau statique?

Non, ce n'est pas comme ça. static les variables sont initialisées avant de démarrer main() et sa durée de vie est l'exécution entière du programme. Ainsi, ils peuvent être returned à partir des fonctions (dans lesquelles ils sont définis) et sont toujours accessibles. Ils ne sont pas local (vers les fonctions) qui s'éteignent lorsque la fonction termine son exécution.

Connexes, citant C11, Chapitre §6.2.4

Un objet dont l'identifiant est déclaré sans le spécificateur de classe de stockage _Thread_local, Et avec une liaison externe ou interne ou avec le spécificateur de classe de stockage static, a une durée de stockage statique. Sa durée de vie correspond à l'exécution complète du programme et sa valeur stockée n'est initialisée qu'une seule fois, avant le démarrage du programme.

Concernant la scope d'une variable static à l'intérieur d'une fonction, oui, elle est limitée à la fonction elle-même, comme mentionné au chapitre §6.2.1,

[...] Si le déclarant ou le spécificateur de type qui déclare l'identifiant apparaît à l'intérieur d'un bloc ou dans la liste des déclarations de paramètres dans une définition de fonction, l'identifiant a une portée de bloc, qui se termine à la fin du bloc associé. [...]

Cela signifie, évidemment, que vous ne pouvez pas utiliser le tableau a en dehors de subFunc(), car a n'est pas visible en dehors de subFunc().

Cependant, lorsque vous return le tableau (le renvoi d'un tableau entraîne une désintégration du pointeur vers le premier élément du tableau, FWIW), car la durée de vie du tableau static est l'exécution complète de le programme, accéder au pointeur retourné (sûrement, dans des limites) est parfaitement valide et légal.

43
Sourav Ghosh

Les variables statiques continuent d'exister même après la fin du bloc dans lequel elles sont définies. Ainsi, la valeur d'une variable statique dans une fonction est conservée entre les appels de fonction répétés à la même fonction. La portée des variables automatiques statiques est identique à celle des variables automatiques, c'est-à-dire qu'elle est locale au bloc dans lequel elle est définie; cependant, le stockage alloué devient permanent pour la durée du programme. Les variables statiques peuvent être initialisées dans leurs déclarations; cependant, les initialiseurs doivent être des expressions constantes et l'initialisation n'est effectuée qu'une seule fois au moment de la compilation lorsque la mémoire est allouée à la variable statique. - source

Les tableaux ou variables statiques ne seront pas libérés lorsque le contrôle sortira de cette fonction. La portée de la variable statique est locale à la fonction dans laquelle elle est déclarée, mais sa durée de vie est tout au long du programme.

21
niyasc

Et pour un tableau statique dans une sous-fonction, le tableau statique sera automatiquement libéré lorsque la sous-fonction appelée sera terminée.

Ce n'est pas vrai. Les tableaux statiques ne sont pas créés lorsque vous entrez dans la fonction et ils ne sont pas détruits lorsque vous la quittez.

Une variable statique, et les données qu'elle contient, sont vraiment n peu comme une variable globale! La seule chose locale à la fonction est le nom . (Vous entendrez des gens parler de la "portée" de la variable - cela signifie "où puis-je utiliser le nom pour y faire référence".)

Ainsi, lorsque vous pensez à la durée de vie d'un tableau statique, vous pouvez remplacer mentalement:

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

avec

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;
}

puis faites comme si personne d'autre dans votre programme ne pouvait toucher cette variable globale.

10
librik

Je me demande pourquoi les tableaux statiques n'ont pas besoin d'être libérés?

  1. Tout ce qui n'est pas alloué par une fonction de gestion de la mémoire (malloc, calloc), comme int a[5] n'a pas besoin d'être explicitement pris en charge libération.

  2. Variables statiques, telles que static int a[5] servent à être accessibles dans la portée locale (ils conservent leurs valeurs entre les appels ultérieurs de la fonction locale). Ils sont créés au moment de la compilation exactement dans ce but, ils ont une durée de vie de programme, donc ce ne serait pas une considération logique de les libérer, même si c'était possible, ce qui n'est pas.

  3. Tout le reste est magistralement expliqué dans d'autres réponses.

3
user3078414

Static variables à l'intérieur d'une fonction, généralement tilisé pour maintenir certaines données dans une portée de la fonction sur plusieurs appels. Ils sont initialisés avant main () et leur durée de vie correspond à l'exécution complète du programme. Donc, cela n'aurait aucun sens s'ils étaient libérés après avoir quitté la fonction. Si vous les libérez, vous planterez la prochaine fois que vous appellerez la fonction car elles ne seront pas référencées.

2
Sanich