Que estratégias e ferramentas são úteis para encontrar vazamentos de memória in.NET?

Escrevi C++ durante 10 anos. Encontrei problemas de memória, mas podem ser corrigidos com um esforço razoável.

Nos últimos dois anos, tenho escrito C#. Acho que ainda tenho muitos problemas de memória. Eles são difíceis de diagnosticar e corrigir devido à não-determinação, e porque a filosofia C# é que você não deve ter que se preocupar com tais coisas quando você definitivamente faz.

um problema em particular que eu acho é que eu tenho que descartar explicitamente e limpar tudo em código. Se não o fizer, os perfis de memória não ajudam porque há tanta confusão a flutuar sobre ti que não consegues encontrar uma fuga dentro de todos os dados que estão a tentar mostrar-te. Pergunto-me se tenho a ideia errada, ou se a ferramenta que tenho não é a melhor.

Que tipo de estratégias e ferramentas são úteis para combater as fugas de memória na. net?

Author: Peter Mortensen, 2008-09-25

15 answers

Uso o Memprofilador do Scitech quando suspeito de uma fuga de memória. Até agora, achei-o muito fiável e poderoso. Salvou-me o couro pelo menos uma vez.

O GC funciona muito bem na IMO.net, mas tal como qualquer outra linguagem ou plataforma, se escrever um código mau, coisas más acontecem.

 45
Author: GEOCHET, 2008-10-09 13:17:22

Apenas para o problema do esquecimento-para-descartar, tente a solução descrita neste post . Eis a essência:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif
 40
Author: Jay Bazuzi, 2008-09-25 16:26:38

Nós usamosAnts Profiler Pro pela Red Gate software no nosso projecto. Funciona muito bem para todas as aplicações. net baseadas na linguagem.

[[3]} descobrimos que o coletor de lixo.NET é muito "seguro" em sua limpeza de objetos na memória (como deveria ser). Ele manteria objetos em torno apenas porque nós poderíamos estar usando-o em algum momento no futuro. Isto significava que precisávamos ser mais cuidadosos sobre o número de objetos que inflacionamos na memória. No final, nós convertemos todos os nossos objetos de dados para um "inflate on-demand" (pouco antes de um campo ser solicitado), a fim de reduzir a sobrecarga de memória e aumentar o desempenho.

EDIT: aqui está mais uma explicação do que eu quero dizer com "inflate on demand."No nosso modelo de objeto do nosso banco de dados, usamos propriedades de um objeto pai para expor o(S) objeto (s) - filho (s). Por exemplo, se tivéssemos algum registro que referenciasse algum outro registro de" detalhe "ou" pesquisa " em uma base de um para um, iríamos estruturá-lo como isto:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class
Descobrimos que o sistema acima criou alguns problemas reais de memória e desempenho quando havia muitos registros na memória. Então nós mudamos para um sistema onde os objetos foram inflados apenas quando eles foram solicitados, e as chamadas de banco de dados foram feitas apenas quando necessário:
class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class
[[3] isso acabou por ser muito mais eficiente porque os objetos foram mantidos fora da memória até que eles foram necessários (o método Get foi acessado). Foi um impulso de desempenho muito grande em limitar acessos à base de dados e um enorme ganho no espaço de memória.
 17
Author: Mark, 2008-10-02 16:19:04

Ainda precisa de se preocupar com a memória quando está a escrever o código gerido, a menos que a sua aplicação seja trivial. Eu vou sugerir duas coisas: primeiro, leia CLR via C# porque ele vai ajudá-lo a entender a gestão de memória em .NET. segundo, aprenda a usar uma ferramenta como CLRProfiler (Microsoft). Isto pode dar-lhe uma ideia do que está a causar a fuga de memória (por exemplo, pode dar uma vista de olhos na sua grande fragmentação de heap de objectos)

 7
Author: Zac Gochenour, 2008-09-25 15:50:53
Estás a usar um código não gerido? Se você não está usando código não gerenciado, de acordo com a Microsoft, vazamentos de memória no sentido tradicional não são possíveis.

A memória utilizada por uma aplicação pode não ser liberada, no entanto, de modo que a alocação de memória de uma aplicação pode crescer ao longo da vida da aplicação.

De Como identificar fugas de memória na linguagem comum em Microsoft.com

Uma fuga de memória pode ocorrer numa. net Quadro aplicação quando utilizar código não gerido como parte do aplicacao. Este código não gerido pode vazar memória, e o Framework. net o tempo de execução não pode resolver esse problema.

Além disso, um projecto só pode parece ter uma fuga de memória. Presente a condição pode ocorrer se muitos grandes objetos (como objetos datáveis) são declarados e, em seguida, adicionados a coleção (como um conjunto de dados). O recursos que estes objectos possuem nunca ser liberado, e os recursos são deixados vivo para toda a corrida de programa. Este parece ser um vazamento, mas na verdade é apenas um sintoma da forma como essa memória é sendo alocado no programa.

Para lidar com este tipo de problema, você pode implementar IDisposable . Se você quiser ver algumas das estratégias para lidar com a gestão de memória, eu sugeriria procurar por IDisposable, XNA, gerenciamento de memória como os desenvolvedores de jogos precisam ter uma coleção de lixo mais previsível e assim tenho de forçar o GC a fazer a sua coisa.

Um erro comum é não remover os manipuladores de eventos que subscrevem um objecto. Uma assinatura de tratador de eventos impedirá que um objeto seja reciclado. Além disso, dê uma olhada na declaração usando que lhe permite criar um escopo limitado para a vida de um recurso.

 6
Author: Timothy Lee Russell, 2008-09-25 16:41:01

Este blog tem alguns avanços realmente maravilhosos usando windbg e outras ferramentas para rastrear vazamentos de memória de todos os tipos. Excelente leitura para desenvolver suas habilidades.

 5
Author: twk, 2008-10-01 00:47:37
Tive uma fuga de memória num serviço de janelas, que arranjei.

Primeiro, tentei MemProfiler . Achei muito difícil de usar e não muito fácil de usar.

Então, eu usei JustTrace {[[5]} que é mais fácil de usar e dá - lhe mais detalhes sobre os objectos que não são eliminados correctamente.

Permitiu-me resolver a fuga de memória facilmente.
 5
Author: billybob, 2015-10-22 15:03:29

Se as fugas que está a observar forem devidas a uma implementação de 'cache' em fuga, este é um cenário em que você pode querer considerar o uso de 'WeakReference'. Isso pode ajudar a garantir que a memória seja liberada quando necessário.

No entanto, IMHO seria melhor considerar uma solução sob medida-só que você realmente sabe quanto tempo você precisa para manter os objetos ao redor, então projetar o código de limpeza apropriado para a sua situação é geralmente a melhor abordagem.

 3
Author: Chris Ballard, 2008-09-25 16:22:09

A melhor coisa a ter em mente é manter o controle das referências aos seus objectos. É muito fácil acabar com referências Penduradas a objetos que você não se importa mais. Se não vais usar mais alguma coisa, livra-te dela.

Habitua-te a usar um fornecedor de cache com expirações deslizantes, para que se algo não for referenciado para uma janela de tempo desejada, seja deslocado e limpo. Mas se ele está sendo acessado muito ele vai dizer em memória.

 2
Author: Gord, 2008-09-25 15:55:53

Uma das melhores ferramentas é usar as ferramentas de depuração para o Windows , e fazer uma descarga de memória do processo usando adplus , Depois usar windbg e o plugin sos para analisar a memória do processo, as linhas e as pilhas de chamadas.

Poderá também usar este método para identificar problemas nos servidores, depois de instalar as ferramentas, partilhar a pasta, depois ligar-se à partilha a partir do servidor, usando (Utilização da rede) e fazer um estoiro ou pendurar o 'dump' do processo.

Depois analisa offline.
 2
Author: Stuart McConnell, 2008-09-25 16:12:48

Big guns - Ferramentas de depuração para o Windows

Esta é uma colecção incrível de ferramentas. Você pode analisar tanto manejados e não gerenciados montes com ele e você pode fazê-lo offline. Isto foi muito útil para depurar um dos nossos ASP.NET aplicações que mantiveram a reciclagem devido ao uso excessivo da memória. Eu só tive que criar um depósito de memória completo do processo de vida em execução no servidor de produção, toda a análise foi feita offline em WinDbg. (Revelou-se que algum desenvolvedor estava a usar a memória em excesso Armazenamento de sessões.)

"se está partido, está..."[[4]} o blog tem artigos muito úteis sobre o assunto.

 2
Author: Constantin, 2008-09-25 16:44:27

Depois de uma das minhas correcções para a aplicação gerida, eu tive a mesma coisa, como verificar se a minha aplicação não terá a mesma fuga de memória após a minha próxima alteração, por isso escrevi algo como o framework de verificação da Libertação de Objectos, por favor dê uma vista de olhos no pacote NuGet Objectreakeeverification. Você pode encontrar uma amostra aqui https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample , e informações sobre esta amostra http://outcoldman.ru/en/blog/show/322

 2
Author: outcoldman, 2012-09-17 04:01:37
Em Visual Studio (Premium ou Enterprise editions), você pode abrir o heap dump e depurar o heap gerenciado. Quando você clicar em um tipo, as páginas abaixo lhe permitirão ver quais outros tipos estão fazendo referência a esses objetos.

Pode utilizar PerfView para uma análise mais detalhada:

  1. No menu memória, seleccione a opção Take Heap Snapshot.

  2. Na janela resultante, seleccione o processo a analisar e carregue Despejar um monte de GC. Você pode opcionalmente congelar o processo ou forçar um GC a ocorrer antes de recolher a fotografia.

  3. Uma vez feito o instantâneo, clique em Fechar.

O Visual Studio e PerfView são na sua maioria úteis para a análise agregada. PerfView é um analisador de amostras, mesmo quando analisa o heap, para que às vezes vai dar uma imagem distorcida de como o monte se parece. Se você precisa perfurar em um objeto específico, ou obter o absoluto a verdade sobre o quadro todo, então. você precisa começar a usar o depurador ou CLR MD.

 2
Author: Maryam Gholami, 2018-08-09 06:09:44

Prefiro dotmemory de Jetbrains

 1
Author: josepainumkal, 2018-03-02 19:12:13
Do Visual Studio 2015 considere usar fora da caixa Ferramenta de diagnóstico da utilização da Memória para coletar e analisar os dados de uso da memória.

A ferramenta de Utilização da memória permite - lhe tirar uma ou mais imagens do heap de memória gerido e nativo para ajudar a compreender o impacto da utilização da memória dos tipos de objectos.

 0
Author: Michael Freidgeim, 2018-05-04 23:03:07