Question

Je suis un peu confus au sujet du fait que dans C # uniquement les types de déchets collectés référence reçoivent. Cela signifie que GC ne capte que les types de référence pour la mémoire de-allocation. Alors qu'est-ce qui se passe avec les types de valeur qu'ils occupent également la mémoire sur la pile?

Était-ce utile?

La solution

Pour commencer, s'ils sont sur la pile ou partie du tas dépend de quel contexte ils font partie - si elles sont dans un type de référence, ils seront sur le tas de toute façon. (Vous devriez considérer combien vous souciez vraiment de la fracture pile / tas de toute façon - comme Eric Lippert a écrit, il est en grande partie un détail de mise en œuvre .)

Cependant, essentiellement la mémoire de valeurs de type est récupérée lorsque le contexte est récupéré - donc quand la pile est sauté par vous retour d'une méthode, que « reconquiert » l'ensemble cadre de pile. De même, si la valeur de type de valeur est en fait une partie d'un objet, alors la mémoire est récupérée lorsque cet objet est détruite.

La réponse courte est que vous n'avez pas à vous soucier de :) (Cela suppose que vous n'avez rien autre que la mémoire à se soucier, bien sûr - si vous avez obtenu struct avec des références à des poignées natives qui ont besoin de libération, qui est un scénario quelque peu différent.)

Autres conseils

  

Je suis un peu confus au sujet du fait que dans C # uniquement les types de déchets collectés référence reçoivent.

Ce n'est pas un fait. Ou plutôt, la vérité ou la fausseté de cette affirmation dépend de ce que vous entendez par « se ramasse-miettes ». Le garbage collector ressemble certainement à des types de valeur lors de la collecte; ces types de valeur peut être en vie et tenant à un type de référence:

struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M(); 

lorsque le garbage collector fonctionne, il semble certainement à s, parce qu'il a besoin de déterminer que s.str est encore en vie.

Ma suggestion:. Clarifier avec précision ce que vous entendez par le verbe "obtient les déchets collectés"

  

GC ne retient que les types de référence pour la mémoire de-allocation.

Encore une fois, ce n'est pas un fait. Supposons que vous ayez une instance de

class C { int x; }

la mémoire pour le nombre entier sera sur le tas ramasse-miettes, et donc récupérés par le ramasse-miettes lorsque l'instance de C devient sans racines.

Pourquoi croyez-vous que le mensonge seule la mémoire de types de référence est désallouée par le collecteur des ordures? La déclaration correcte est que la mémoire qui a été alloués par le garbage collector est désallouées par le garbage collector, que je pense tout à fait logique. Le GC a alloué ce qu'il est si responsable de ce nettoyage.

  

Alors qu'est-ce qui se passe avec les types de valeur qu'ils occupent également la mémoire sur la pile?

Rien du tout ce qui leur arrive. Rien ne doit leur arriver. La pile est d'un million d'octets. La taille de la pile est déterminée lorsque le fil se met en marche; il commence à un million d'octets et il reste un million d'octets tout au long de l'exécution entière du fil. Mémoire sur la pile est ni créée ni détruite; que son contenu sont modifiés.

Il y a trop de verbes utilisés dans cette question, comme détruite, remis en état, désallouée, enlevé. Cela ne correspond pas bien avec ce qui se passe réellement. Une variable locale cesse simplement d'être, style perroquet norvégien .

Un procédé a un point d'entrée unique, la première chose qui se produit est que le pointeur de pile du processeur est ajustée. Création d'un « cadre de pile », espace de stockage pour les variables locales. Les garanties CLR que cet espace est initialisé à 0, pas autrement une fonctionnalité que vous utilisez fortement en C # en raison de la règle d'affectation définitive.

Une méthode a un seul point de sortie, même si vous le code de la méthode est truffé de multiples déclarations de return. À ce moment-là, le pointeur de la pile est simplement restauré à sa valeur d'origine. En effet, il « oublie » que les variables locales où jamais là. Leurs valeurs ne sont pas « épurés » de quelque façon, les octets sont toujours là. Mais ils ne durent pas longtemps, le prochain appel dans votre programme vont les remplacer à nouveau. La règle zéro initialisation CLR garantit que vous ne pouvez jamais observer ces anciennes valeurs, ce serait peu sûr.

Très, très rapide, ne prend pas plus d'un seul cycle de traitement. Un visible effet secondaire de ce comportement dans le langage C # est que les types de valeur ne peuvent pas avoir un finaliseur. Veiller à aucun travail supplémentaire doit être fait.

Un type de valeur sur la pile est retirée de la pile quand elle est hors de portée.

Les types de valeur sont détruits dès qu'ils sont hors de portée.

types de valeur obtiendraient désallouée lorsque le cadre de la pile est retirée après qu'il a été exécuté, je suppose

voudrais également ajouter que la pile est à un niveau de fil, et tas est au niveau du domaine d'application.

Ainsi, quand un fil se termine il RECLAM la pile de mémoire utilisée par ce fil spécifique.

Chaque valeur instance de type .NET fera partie de quelque chose d'autre, ce qui pourrait être une instance de type valeur renfermant plus, un objet en tas, ou un cadre de pile. Chaque fois que l'une de ces choses CONCRETISEE, toutes les structures qui les composent entreront aussi en être; ces structures seront alors continuer à exister aussi longtemps que la chose qui les contient ne. Lorsque la chose qui contient la structure cesse d'exister, la structure sera ainsi. Il est impossible de détruire une structure sans détruire le récipient, et il est impossible de détruire quelque chose qui contient une ou plusieurs structures sans détruire les structures qui y sont contenues.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top