35 votes

Les références circulaires sont-elles la cause d'une fuite de mémoire?

Je suis en train de lancer en bas d'une fuite de mémoire dans une application windows forms. Je suis à la recherche maintenant à un formulaire qui contient plusieurs formulaires imbriqués. Ce qui m'inquiète, c'est que les formes d'enfants, en leur constructeur, prendre une référence au formulaire parent, et de la garder dans un champ. Il me semble donc que venir garbage-collection le temps:

Parent a une référence à l'enfant forme, via la collection de contrôles (formulaire enfant est embarqué là-bas). Formulaire d'enfant n'est pas GC avais.

Formulaire enfant a une référence au formulaire parent, par le membre privé de terrain. Formulaire Parent n'est pas GC avais.

Est-ce une bonne compréhension de la façon dont le garbage collector évaluer la situation? De toute façon, pour "prouver" pour des fins de test?

39voto

Charles Bretana Points 59899

Excellente question!

Non, les Deux formes seront (peut être) GC avais parce que la GC n'est pas directement chercher des références dans d'autres références. Il ne regarde que ce que l'on appelle "Root" références ... Ceci inclut la référence à des variables sur la pile, (Variable est sur la pile, l'objet réel est, bien sûr, sur le tas), les références de variables dans les registres du CPU, et les variables de référence que sont les champs statiques dans les classes...

Toutes les autres variables de référence sont uniquement accessibles (et GC avais) si elles sont référencées dans une propriété de l'un des "racine" de référence des objets trouvés par le processus ci-dessus... (ou dans un objet référencé par une référence à un objet racine, etc...)

De sorte que si l'une des formes est référencé quelque part d'autre d'une "racine" de référence - les deux formes sera à l'abri de la GC.

seule façon que je peux penser à "prouver" qu'il, (sans l'aide de la trace de mémoire utilitaires) serait de créer quelques centaines de milliers de ces formes, dans une boucle à l'intérieur d'une méthode, puis, alors que dans la méthode, regarder à l'application de la mémoire, puis la sortie de la méthode, l'appel de la GC, et de regarder l'empreinte de nouveau.

15voto

Vilx- Points 37939

Comme d'autres l'ont déjà dit, les références circulaires ne posent aucun problème à GC. Je voudrais juste ajouter qu’un lieu commun de fuite de mémoire dans .NET sont les gestionnaires d’événements. Si l'un de vos formulaires a un gestionnaire d'événement attaché à un autre objet qui est "vivant", il est alors fait référence à votre formulaire et le formulaire ne sera pas GC'd.

12voto

Jason Points 125291

La collecte des ordures œuvres par application de suivi des racines. Application racines sont des emplacements de stockage qui contiennent des références à des objets sur le tas managé (ou null). Dans .NET, les racines sont

  1. Les références à des objets globaux
  2. Les références à des objets statiques
  3. Les références à des champs statiques
  4. Références sur la pile d'objets locaux
  5. Références sur la pile pour objet les paramètres passés aux méthodes
  6. Les références à des objets en attente d'être finalisé
  7. Les références dans les registres du CPU à des objets sur le tas managé

La liste des racines actives est maintenu par le CLR. Le garbage collector œuvres en regardant les objets sur le tas managé et de voir qui sont toujours accessibles par l'application, qui est accessible par une racine de l'application. Un tel objet est considéré comme enraciné.

Maintenant, supposons que vous disposez d'un formulaire parent qui contient des références à l'enfant des formes et de l'enfant ces formulaires contiennent des références au formulaire parent. En outre, supposons que l'application ne contient plus une des références pour le parent ou l'un des formulaires enfants. Alors, pour les fins de la collecte des déchets, ces objets gérés sont plus enracinés et sera le garbage collector du prochain démarrage de la collecte des ordures se produit.

5voto

Lars Truijens Points 24005

Si à la fois le parent et l'enfant ne sont pas référencés, mais qu'ils se référent uniquement, ils sont passés à GCed.

Demandez à un profileur de mémoire de vérifier votre application et de répondre à toutes vos questions. Je peux recommander http://memprofiler.com/

2voto

user814688 Points 11

Je voudrais faire écho à Vilx la remarque sur les événements, et de recommander un modèle de conception qui permet de s'attaquer à elle.

Disons que vous avez un type qui est une source de l'événement, par exemple:

interface IEventSource
{
    event EventHandler SomethingHappened;
}

Voici un extrait d'une classe qui gère les événements à partir d'instances de ce type. L'idée est qu'à chaque fois que vous affectez une nouvelle instance de la propriété, vous devez d'abord vous désabonner d'une précédente affectation, puis abonnez-vous à la nouvelle instance. Le nul de contrôles de veiller à la bonne limite de comportements, et plus au point, de simplifier disposition: tout ce que vous faites est nulle la propriété.

Ce qui amène le point d'élimination. Toute la classe qui s'abonne aux événements doit implémenter l'interface IDisposable parce que les événements sont gérés ressources. (N. B. j'ai sauté une bonne mise en œuvre du modèle dispose dans l'exemple par souci de concision, mais vous voyez l'idée).

class MyClass : IDisposable
{
    IEventSource m_EventSource;
    public IEventSource EventSource
    {
        get { return m_EventSource; }
        set
        {
            if( null != m_EventSource )
            {
                m_EventSource -= HandleSomethingHappened;
            }
            m_EventSource = value;
            if( null != m_EventSource )
            {
                m_EventSource += HandleSomethingHappened;
            }
        }
    }

    public Dispose()
    {
        EventSource = null;
    }

    // ...
}

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