Disons que j'ai le code C suivant:
int main () {
int *p = malloc(10 * sizeof *p);
*p = 42;
return 0; //Exiting without freeing the allocated memory
}
Lorsque je compile et exécute ce programme C, c'est-à-dire après avoir alloué un peu d'espace en mémoire, cette mémoire que j'ai allouée sera-t-elle toujours allouée (c'est-à-dire occupant essentiellement de l'espace) après avoir quitté l'application et le processus se termine?
c
memory-management
Andreas Grech
la source
la source
Réponses:
Cela dépend du système d'exploitation. La majorité des systèmes d'exploitation modernes (et tous les principaux) libéreront de la mémoire non libérée par le programme à la fin.
S'en remettre à cela est une mauvaise pratique et il vaut mieux la libérer explicitement. Le problème n'est pas seulement que votre code semble mauvais. Vous pouvez décider d'intégrer votre petit programme dans un programme plus grand et plus long. Puis, un peu plus tard, vous devrez passer des heures à dépister les fuites de mémoire.
S'appuyer sur une fonctionnalité d'un système d'exploitation rend également le code moins portable.
la source
En général, les systèmes d'exploitation modernes à usage général nettoient après l'arrêt des processus . Cela est nécessaire parce que l'alternative est que le système perd des ressources au fil du temps et nécessite un redémarrage en raison de programmes mal écrits ou qui ont simplement des bogues rares qui fuient des ressources.
Le fait que votre programme libère de toute façon explicitement ses ressources peut être une bonne pratique pour diverses raisons, telles que:
Cependant, voici une raison pour ne pas libérer de mémoire: un arrêt efficace . Par exemple, supposons que votre application contienne un grand cache en mémoire. Si, à sa sortie, il traverse toute la structure du cache et le libère une pièce à la fois, cela ne sert à rien et gaspille des ressources. En particulier, considérez le cas où les pages de mémoire contenant votre cache ont été échangées sur le disque par le système d'exploitation; en parcourant la structure et en la libérant, vous ramenez toutes ces pages en mémoire en une seule fois , gaspillant beaucoup de temps et d'énergie pour aucun avantage réel, et peut-être même provoquant l'échange d'autres programmes du système!
À titre d'exemple connexe, il existe des serveurs hautes performances qui fonctionnent en créant un processus pour chaque demande, puis en le faisant quitter une fois terminé; par ce moyen, ils n'ont même pas besoin de suivre l' allocation de mémoire , et ne font jamais du tout de libération ou de garbage collection, puisque tout disparaît simplement dans la mémoire libre du système d'exploitation à la fin du processus. (Le même genre de chose peut être fait dans un processus en utilisant un allocateur de mémoire personnalisé, mais nécessite une programmation très minutieuse; en faisant essentiellement sa propre notion de «processus légers» dans le processus du système d'exploitation.)
la source
Mes excuses pour avoir publié si longtemps après le dernier message sur ce fil.
Un point supplémentaire. Tous les programmes ne parviennent pas à des sorties élégantes. Les plantages et les ctrl-C, etc. entraîneront la fermeture d'un programme de manière incontrôlée. Si votre système d'exploitation ne libère pas votre tas, nettoie votre pile, supprime les variables statiques, etc., vous finirez par planter votre système à cause de fuites de mémoire ou pire.
En dehors de cela, les plantages / pannes dans Ubuntu, et je soupçonne que tous les autres systèmes d'exploitation modernes, ont des problèmes avec les ressources "gérées". Les sockets, fichiers, périphériques, etc. peuvent rester "ouverts" lorsqu'un programme se termine / plante. C'est également une bonne pratique pour fermer tout ce qui a une «poignée» ou un «descripteur» dans le cadre de votre nettoyage avant une sortie gracieuse.
Je développe actuellement un programme qui utilise fortement les sockets. Lorsque je suis coincé dans un blocage, je dois ctrl-c hors de celui-ci, bloquant ainsi mes prises. J'ai ajouté un std :: vector pour collecter une liste de toutes les sockets ouvertes et un gestionnaire de sigaction qui attrape sigint et sigterm. Le gestionnaire parcourt la liste et ferme les sockets. Je prévois de faire une routine de nettoyage similaire à utiliser avant les lancers qui mèneront à une interruption prématurée.
Quelqu'un souhaite-t-il commenter cette conception?
la source
Ce qui se passe ici ( dans un système d'exploitation moderne ), c'est que votre programme s'exécute dans son propre «processus». Il s'agit d'une entité de système d'exploitation dotée de son propre espace d'adressage, de descripteurs de fichiers, etc.
malloc
appels allouent la mémoire du « tas » ou des pages de mémoire non alloués qui sont affectés à votre processus.Lorsque votre programme se termine, comme dans cet exemple, toutes les ressources affectées à votre processus sont simplement recyclées / détruites par le système d'exploitation. Dans le cas de la mémoire, toutes les pages mémoire qui vous sont attribuées sont simplement marquées comme «libres» et recyclées pour l'utilisation d'autres processus. Les pages sont un concept de niveau inférieur à celui de malloc - en conséquence, les spécificités de malloc / free sont toutes simplement emportées au fur et à mesure que tout est nettoyé.
C'est l'équivalent moral de, lorsque vous avez fini d'utiliser votre ordinateur portable et que vous voulez le donner à un ami, vous ne vous souciez pas de supprimer individuellement chaque fichier. Vous formatez simplement le disque dur.
Tout cela étant dit, comme le font remarquer tous les autres répondants, se fier à ceci n'est pas une bonne pratique:
la source
Oui. Le système d'exploitation nettoie les ressources. Eh bien ... les anciennes versions de NetWare ne l'ont pas fait.
Edit: Comme l'a souligné San Jacinto, il existe certainement des systèmes (à part NetWare) qui ne font pas cela. Même dans les programmes jetables, j'essaie de prendre l'habitude de libérer toutes les ressources juste pour garder l'habitude.
la source
Oui, le système d'exploitation libère toute la mémoire lorsque le processus se termine.
la source
malloc
ne peut que promettre ce que C fera de la mémoire; de par sa conception, C ne garantit pas grand-chose concernant le comportement en dehors de C lui-même. Si l'application meurt de manière inattendue, toutes les promesses faites par la bibliothèque d'exécution sont nulles et non avenues, car elle n'est plus vivante pour les tenir.Cela dépend, les systèmes d'exploitation le nettoieront généralement pour vous, mais si vous travaillez par exemple sur un logiciel intégré, il se peut qu'il ne soit pas publié.
Assurez-vous simplement de le libérer, cela peut vous faire gagner beaucoup de temps plus tard, lorsque vous voudrez peut-être l'intégrer à un grand projet.
la source
Cela dépend vraiment du système d'exploitation, mais pour tous les systèmes d'exploitation que vous rencontrerez jamais, l'allocation de mémoire disparaîtra lorsque le processus se terminera.
la source
Je pense que la libération directe est la meilleure. Un comportement non défini est la pire des choses, donc si vous avez accès pendant qu'il est encore défini dans votre processus, faites-le, il y a beaucoup de bonnes raisons que les gens ont données pour cela.
Quant à savoir où, ou si, j'ai trouvé cela dans W98, la vraie question était «quand» (je n'ai pas vu un article insistant sur cela). Un petit programme de modèle (pour l'entrée MIDI SysEx, utilisant divers espaces malloc'd) libérerait de la mémoire dans le bit WM_DESTROY du WndProc, mais quand je l'ai transplanté dans un programme plus grand, il s'est écrasé à la sortie. J'ai supposé que cela signifiait que j'essayais de libérer ce que le système d'exploitation avait déjà libéré lors d'un nettoyage plus important. Si je l'ai fait sur WM_CLOSE, puis appelé DestroyWindow (), tout a bien fonctionné, sortie propre instantanée.
Bien que ce ne soit pas exactement la même chose que les tampons MIDI, il existe une similitude en ce sens qu'il est préférable de garder le processus intact, de nettoyer complètement, puis de quitter. Avec des morceaux de mémoire modestes, c'est très rapide. J'ai trouvé que de nombreux petits tampons fonctionnaient plus rapidement en fonctionnement et en nettoyage que moins de grands tampons.
Des exceptions peuvent exister, comme quelqu'un l'a dit en évitant de retirer de gros morceaux de mémoire d'un fichier d'échange sur disque, mais même cela peut être minimisé en gardant des espaces alloués plus nombreux et plus petits.
la source