it-swarm-fr.com

Pourquoi les livres .NET parlent-t-il d'une allocation de mémoire de pile vs tas?

Il semble que tous les parlements de livre .net sur des types de valeur VS Types de référence et en font un état (souvent incorrectement) où chaque type est stocké - le tas ou la pile. Habituellement, il est dans les premiers chapitres et présenté comme un fait tout important. Je pense que c'est même couvert sur examens de certification . Pourquoi la pile vs est-elle même importante pour (débutant) .NET développeurs? Vous allouez des choses et ça fonctionne juste, non?

36
Greg

Je suis devenu convaincu que la principale raison de cette information est considérée comme importante. tradition. Dans des environnements non gérés, la décollage entre la pile et le tas est important et Nous devons allouer manuellement et supprimer la mémoire que nous utilisons. Maintenant, la collecte des ordures prend soin de la direction, alors ils ignorent ce bit. Je ne pense pas que le message ait vraiment obtenu que nous n'avons pas à prendre en charge quel type de mémoire est utilisé non plus.

Comme l'a souligné Fede, Eric Lippert a des choses très intéressantes à dire à ce sujet: http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/Le-truth-about-value -Types.aspx .

À la lumière de ces informations, vous pouvez ajuster mon premier paragraphe à la lecture fondamentalement: "La raison pour laquelle les gens incluent ces informations et supposent qu'il est important d'être en raison d'informations incorrectes ou incomplètes combinées à la nécessité de ces connaissances dans le passé."

Pour ceux qui pensent qu'il est toujours important pour des raisons de performance: quelles actions prenez-vous pour déplacer quelque chose du tas à la pile si vous mesurez les choses et découvrez que cela comptait? Plus probablement, vous trouverez une manière complètement différente d'améliorer la performance pour la zone problématique.

37
John Fisher

Il semble que tous les parlements de livre .net sur des types de valeur VS Types de référence et en font un état (souvent incorrectement) où chaque type est stocké - le tas ou la pile. Habituellement, il est dans les premiers chapitres et présenté comme un fait tout important.

Je suis complètement d'accord; Je vois ça tout le temps.

Pourquoi les livres .NET parlent-t-il d'une allocation de mémoire de pile vs tas?

Une partie de la raison est parce que beaucoup de gens sont venus chez C # (ou d'autres langues .net) d'un fond C ou C++. Étant donné que ces langues ne respectent pas pour vous les règles relatives au stockage de la vie, vous devez connaître ces règles et mettre en œuvre votre programme avec précaution pour les suivre.

Maintenant, connaître ces règles et les suivre en C ne signifie pas exiger que vous comprenez "le tas" et "la pile". Mais si vous comprenez comment les structures de données fonctionnent, il est souvent plus facile de comprendre et de suivre les règles.

Lors de la rédaction d'un livre de débutant, il est naturel pour un auteur d'expliquer les concepts dans le même ordre que ils les appris. Ce n'est pas nécessairement l'ordre qui a du sens pour l'utilisateur. J'ai récemment été éditeur technique pour le livre de débutant C # 4 de Scott Dorman, et l'une des choses que j'ai aimées était que Scott a choisi un ordre assez sensible pour les sujets, plutôt que de commencer sur ce qui sont des sujets assez avancés dans la gestion de la mémoire.

Une autre partie de la raison est que certaines pages de la documentation MSDN mettent fortement l'accent sur les considérations de stockage. Particulièrement plus âgée de la documentation MSDN qui est toujours suspendue à partir des premiers jours. Une grande partie de cette documentation a des erreurs subtiles qui n'ont jamais été excises et que vous devez vous rappeler qu'il a été écrit à une période donnée en histoire et à un public particulier.

Pourquoi la pile vs est-elle même importante pour (débutant) .NET développeurs?

À mon avis, ça ne le fait pas. Ce qui est beaucoup plus important de comprendre, c'est des choses comme:

  • Quelle est la différence de sémantique de copie entre un type de référence et un type de valeur?
  • Comment un paramètre "Ref int x" se comporte-t-il?
  • Pourquoi les types de valeur devraient-ils être immuables?

Etc.

Vous allouez des choses et ça fonctionne juste, non?

C'est l'idéal.

Maintenant, il y a des situations dans lesquelles il importe. La collecte des ordures est géniale et relativement peu coûteuse, mais ce n'est pas gratuit. Copier de petites structures autour est relativement peu coûteux, mais n'est pas gratuit. Il existe des scénarios de performance réalistes dans lesquels vous devez équilibrer le coût de la pression de recouvrement contre le coût de la copie excessive. Dans ces cas, il est très utile d'avoir une forte compréhension de la taille, de l'emplacement et de la durée de vie réelle de toute la mémoire pertinente.

De même, il existe des scénarios interop réalistes dans lesquels il est nécessaire de savoir ce qui se passe sur la pile et ce qui se passe sur le tas, et ce que le collecteur des ordures pourrait se déplacer. C'est pourquoi C # a des fonctionnalités telles que "fixes", "Spectacle" et ainsi de suite.

Mais ce sont tous des scénarios avancés. Idéalement, un programmeur débutant doit s'inquiéter de rien de de ces choses.

37
Eric Lippert

Vous manquez tous le point. La raison pour laquelle la distinction de la pile/du tas est importante est à cause de étendue.

struct S { ... }

void f() {
    var x = new S();
    ...
 }

Une fois -x sort hors de portée, l'objet créé est catégoriquement parti. C'est seulement parce qu'il est alloué sur la pile, pas le tas. Il n'y a rien qui aurait pu entrer dans la partie "..." de la méthode qui peut changer ce fait. En particulier, tout appel de mission ou de méthode ne pouvait avoir que :copies de la structure S, non créé de nouvelles références pour lui permettre de continuer à vivre.

class C { ... }

void f() {
     var x = new C();
     ...
}

Histoire totalement différente! Puisque X est maintenant sur le tas, son objet (c'est-à-dire le objet lui-même, pas une copie de celui-ci) pourrait très bien continuer à vivre après x sort hors de portée. En fait, la seule façon dont il ne sera pas continuer à vivre est si x est la seule référence à elle. Si des affectations ou des appels de méthode dans la partie "..." ont créé d'autres références qui sont toujours "en direct" à l'heure x dépasse de la portée, alors cet objet continuera à vivre.

C'est un concept très important et le seul moyen de vraiment comprendre "quoi et pourquoi" est de connaître la différence entre la pile et l'allocation de tas.

13
JoelFan

Eh bien, je pensais que c'est tout le point d'environnements gérés. J'irrais même aller aussi loin que d'appeler cela un détail de mise en œuvre du temps d'exécution sous-jacent que vous ne devriez pas faire d'hypothèses, car cela pourrait changer à tout moment.

Je ne sais pas grand chose sur .net, mais aussi loin que je sache, sa disparition avant exécution. Le JIT, par exemple, pourrait effectuer analyse d'évacuation et quoi de pas et tout de suite que vous auriez soudainement des objets allongés sur la pile ou simplement dans certains registres. Vous ne pouvez pas le savoir.

Je suppose que certains livres couvrent simplement parce que les auteurs attribuent une grande importance à cela, ou parce qu'ils supposent que leur public est (par exemple, si vous avez écrit un "C # pour les programmeurs C++", vous devriez probablement couvrir le sujet).

Néanmoins, je pense qu'il n'y a pas beaucoup plus à dire que "la mémoire est gérée". Sinon, les gens pourraient tirer de mauvaises conclusions.

5
back2dos

Vous devez comprendre comment la répartition de la mémoire fonctionne pour l'utiliser efficacement même si vous n'avez pas à gérer explicitement. Ceci s'applique à peu près toutes les abstractions en informatique.

2
Kirk Fernandes

Comme vous le dites, c # est censé abstrait de la gestion de la mémoire abstraite et la répartition des tas de pile sont des détails de mise en œuvre qui, en théorie, le développeur ne doit pas avoir besoin de savoir.

Le problème est que certaines choses sont vraiment difficiles à expliquer de manière intuitive sans faire référence à ces détails de la mise en œuvre. Essayez d'expliquer le comportement observable lorsque vous modifiez des types de valeur mutable - il est presque impossible de faire sans se référer à la distinction de la pile/du tas. Ou essayez d'expliquer pourquoi même avoir des types de valeur dans la langue en premier lieu et quand vous les utiliseriez? Vous devez comprendre la distinction afin de donner un sens à la langue.

Notez que les livres sur Say Python ou JavaScript ne constituent pas une grosse affaire en dehors de cela s'ils le mentionnent. C'est parce que tout est le tas alloué ou immuable, ce qui signifie que les différentes sémantiques de copier ne font jamais Entrez en jeu. Dans ces langues, l'abstraction de la mémoire fonctionne, en C #, il est fuyant.

0
JacquesB