17 votes

Quelle est la philosophie de gestion de la mémoire en C++?

Quel est le facteur de conception dans la gestion de la mémoire en C++? Par exemple: pourquoi y a-t-il une fuite de mémoire quand un programme ne libère pas un objet mémoire avant de se terminer? Une bonne conception de langage de programmation ne devrait-elle pas maintenir une "foo-table" qui prend en charge cette situation? Je sais que je suis un peu naïf, mais quelle est la philosophie de conception de la gestion de mémoire en C++ par rapport aux classes, aux structures, aux méthodes, aux interfaces, aux classes abstraites?

Évidemment, on ne peut pas se souvenir parfaitement de chaque spécificité du C++. Quel est le moteur principal de la conception de la gestion de la mémoire?

40voto

James McNellis Points 193607

Quel est le principal concept de conception de la gestion de la mémoire ?

Dans presque tous les cas, vous devriez utiliser une gestion automatique des ressources. Fondamentalement :

  • Partout où c'est possible, préférez créer des objets avec une durée de stockage automatique (c'est-à-dire sur la pile ou locale à une fonction)
  • Chaque fois que vous devez utiliser une allocation dynamique, utilisez la Gestion des Ressources Liées à la Portée (SBRM; plus communément appelée Resource Acquisition is Initialization ou RAII).

Vous avez rarement besoin d'écrire votre propre conteneur RAII : la bibliothèque standard de C++ fournit tout un ensemble de conteneurs (par exemple, vector et map) et les smart pointers comme shared_ptr (à partir de C++ TR1, C++0x, et Boost) fonctionnent très bien pour la plupart des situations courantes.

Fondamentalement, dans un code C++ vraiment bon, vous ne devriez jamais appeler vous-même delete1 pour nettoyer la mémoire que vous avez allouée : la gestion de la mémoire et le nettoyage des ressources doivent toujours être encapsulés dans un conteneur quelconque.

1. De toute évidence, l'exception ici est lorsque vous implémentez vous-même un conteneur RAII, puisque ce conteneur doit être responsable du nettoyage de ce que vous possédez.

4voto

Jerry Coffin Points 237758

Il n'est pas tout à fait clair si vous parlez de la philosophie de ce qui est intégré dans C++, ou de la façon de l'utiliser de manière à éviter les fuites de mémoire.

La principale façon de prévenir les fuites de mémoire (et autres fuites de ressources) est connue sous le nom de RAII (Resource Acquisition Is Initialization) ou SBRM (Scope Bound Resource Management). Dans les deux cas, l'idée de base est assez simple : comme les objets avec une durée de stockage auto sont automatiquement détruits à la sortie de leur portée, vous allouez de la mémoire dans le constructeur d'un tel objet, et libérez la mémoire dans son destructeur.

En ce qui concerne C++ lui-même, il n'a pas vraiment de philosophie. Il fournit des mécanismes, mais laisse au programmeur le soin de décider quel mécanisme est approprié pour la situation en question. C'est souvent le RAII. Parfois, cela peut être un collecteur de déchets. D'autres fois, cela peut être différents types de gestionnaires de mémoire personnalisés. Bien sûr, parfois, il s'agit d'une combinaison de deux ou des trois, ou quelque chose de totalement différent.

Édition : Quant à pourquoi C++ fait les choses de cette manière, c'est assez simple : presque tout autre choix rendrait le langage inadapté à au moins certains types de problèmes, y compris un certain nombre pour lesquels il était clairement destiné à convenir. L'un des plus évidents était la capacité de fonctionner sur une machine "nue" avec un minimum de structure de support (par exemple, pas de système d'exploitation)

3voto

Ed S. Points 70246

pourquoi y a-t-il une fuite de mémoire lorsqu'un programme ne libère pas un objet mémoire avant de se terminer ?

Eh bien, le système d'exploitation nettoie généralement votre désordre pour vous. Cependant, que se passe-t-il lorsque votre programme s'exécute pendant une durée arbitraire et que vous avez fuité tellement de mémoire que vous ne pouvez plus en allouer ? Vous plantez, et ce n'est pas bon.

La conception d'un bon langage de programmation n'est-elle pas censée maintenir une "table foo" qui prend en charge cette situation ?

Non. Certains langages de programmation ont une gestion automatisée de la mémoire, d'autres non. Il y a des avantages et des inconvénients à ces deux modèles. Les langages avec une gestion manuelle de la mémoire vous permettent de dire quand et où les ressources sont allouées et libérées, c'est-à-dire que c'est très déterministe. Un débutant relatif écrira cependant inévitablement du code qui fuit en s'adaptant à la gestion de la mémoire.

Les schémas automatisés sont formidables pour le programmeur, mais vous n'obtenez pas le même niveau de déterminisme. Si je suis en train d'écrire un pilote de matériel, ce modèle pourrait ne pas être bon pour moi. Si j'écrivais une simple interface graphique, alors je me soucie probablement peu du fait que certains objets persistent un peu plus longtemps qu'ils ne le devraient, donc je choisirais toujours un schéma de gestion automatisée. Cela ne signifie pas que les langages avec GC ne sont destinés qu'à des tâches 'simples', certaines tâches nécessitent simplement un contrôle plus étroit de vos ressources. Toutes les plateformes n'ont pas plus de 4 Go de mémoire pour vous amuser).

Il existe des modèles que vous pouvez utiliser pour vous aider dans la gestion de la mémoire. L'exemple canonique serait RAII (Resource Allocation is Initialization)

3voto

Joe Points 17829

En C et C++, on considère que c'est à vous, le programmeur, de savoir quand vous avez terminé avec la mémoire que vous avez allouée. Cela évite au runtime du langage de savoir ce qui a été alloué, ainsi que les tâches associées (comptage des références, ramasse-miettes, etc.) nécessaires pour "nettoyer" quand c'est nécessaire.

Le principe fondamental est le suivant : si vous l'allouez, vous devez le libérer. (malloc/free, new/delete)

Il existe plusieurs méthodes pour vous aider à gérer cela afin que vous n'ayez pas besoin de vous en souvenir explicitement. RAII et les implémentations de pointeurs intelligents qui fournissent des conteneurs le font de manière extrêmement utile et puissante pour gérer la mémoire en fonction de la création et de la destruction d'objets. Ils vous feront gagner des heures de temps.

1voto

Laurence Gonsalves Points 50783

Philosophiquement, je pense qu'il y a deux choses qui expliquent pourquoi C++ n'a pas de ramasse-miettes (ce qui semble être ce que vous voulez dire) :

  • Compatibilité avec C. C++ essaie d'être très compatible avec C, pour le meilleur ou pour le pire. C n'avait pas de ramasse-miettes, donc C++ non plus, du moins pas par défaut. Je suppose que l'on pourrait résumer cela à des "raisons historiques".

  • La philosophie du "vous ne payez que ce que vous utilisez". C++ essaie d'éviter d'imposer des frais supplémentaires par rapport à C à moins que vous ne le demandiez explicitement. Ainsi, vous ne payez le prix des exceptions que si vous en lancez réellement une, etc. Certains soutiennent que la ramasse-miettes imposerait un coût chaque fois qu'un objet est alloué sur le tas, de sorte qu'elle ne pourrait pas être le comportement par défaut en C++.

    Il convient de noter qu'il y a en fait un assez grand débat sur la question de savoir si la ramasse-miettes est effectivement plus ou moins efficace que la gestion manuelle de la mémoire. Les meilleurs ramasse-miettes veulent généralement pouvoir déplacer des choses, et C++ autorise l'arithmétique des pointeurs (encore une fois, héritée de C) ce qui rend très difficile le travail avec un tel ramasse-miettes en C++.

Voici la réponse (pas vraiment directe) de Stroustrup à "Pourquoi C++ n'a-t-il pas de ramasse-miettes?":

Si vous voulez une ramasse-miettes automatique, il existe de bons ramasse-miettes commerciaux et en domaine public pour C++. Pour les applications où la ramasse-miettes est appropriée, C++ est un excellent langage à ramasse-miettes avec des performances qui se comparent favorablement à d'autres langages à ramasse-miettes. Voir Le Langage de Programmation C++ (3ème édition) pour une discussion sur la ramasse-miettes automatique en C++. Voir également le site de Hans-J. Boehm pour la ramasse-miettes en C et C++.

De plus, C++ supporte des techniques de programmation qui permettent une gestion sûre et implicite de la mémoire sans ramasse-miettes.

C++0x offre un ABI à ramasse-miettes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X