Pergunta

Em .NET perspectiva:

  • O que é um vazamento de memória?
  • Como você pode determinar se o aplicativo vazamentos?Quais são os efeitos?
  • Como você pode evitar um vazamento de memória?
  • Se seu aplicativo tem vazamento de memória, faz com que ela vá embora quando o processo termina ou é morto?Ou fazer vazamentos de memória em seu aplicativo afetar outros processos no sistema, mesmo após a conclusão do processo?
  • E o que dizer de código não gerenciado acessado através de Interoperabilidade e/ou P/Invoke?
Foi útil?

Solução

A melhor explicação que eu já vi é o Capítulo 7 da graça Fundamentos da Programação de e-book.

Basicamente, em .NET um vazamento de memória ocorre quando objetos referenciados são enraizadas e, portanto, não pode ser coletado pelo coletor de lixo.Isso ocorre acidentalmente quando você segurar referências além do escopo pretendido.

Você vai saber que você tem vazamentos quando você começar a OutOfMemoryExceptions ou o seu uso de memória vai além do que seria de esperar (PerfMon tem bons contadores de memória).

Compreensão .NET's modelo de memória é a melhor forma de evitá-lo.Especificamente, a compreensão de como o coletor de lixo funciona e como referências de trabalho — mais uma vez, refiro-me ao capítulo 7 do livro eletrônico.Também, tome cuidado com as armadilhas comuns, provavelmente, a mais comum sendo eventos.Se o objeto Um é registado um evento no objeto B, e , em seguida, objeto de Um vão ficar lá até que o objeto B desaparece, porque B contém uma referência para Um.A solução é anular o registo de eventos quando você está feito.

É claro, uma boa memória de perfil permite que você veja os gráficos de objetos e explorar o aninhamento/referência de seus objetos para ver onde as referências estão vindo e o que o objeto raiz é responsável (a red-gate formigas perfil, JetBrains dotMemory, memprofiler são realmente boas escolhas, ou você pode usar somente texto O WinDbg e SOS, mas eu recomendaria fortemente comercial/visual do produto, a menos que você é um verdadeiro guru).

Eu acredito que o código não gerenciado é assunto para o seu típico de fugas de memória, exceto que são referências comuns são gerenciadas pelo coletor de lixo.Eu poderia estar errado sobre este último ponto.

Outras dicas

Estritamente falando, um vazamento de memória está consumindo de memória que é "mais usado" pelo programa.

"Não usado" tem mais de um significado, que poderia significar "não há mais referência a ele", isto é, totalmente irrecuperável, ou pode significar, referenciado, recuperável, não utilizados, mas o programa mantém as referências de qualquer maneira.Só mais tarde se aplica .Líquido para perfeitamente objetos gerenciados.No entanto, nem todas as classes são perfeitos e em algum ponto de um subjacente não gerenciado implementação poderia vazamento de recursos permanentemente para esse processo.

Em todos os casos, a aplicação consome mais memória do que o estritamente necessário.Os lados de efeitos, dependendo da quantidade perdida, poderia ir de nenhum, a desaceleração causada pelo excesso de coleção, para uma série de exceções de memória e, finalmente, um erro fatal seguido por forçou o encerramento do processo.

Você sabe que uma aplicação tem um problema de memória quando a monitorização mostra que mais e mais memória é alocada para o processo de após cada ciclo de coleta de lixo.Em tal caso, você quer manter muita memória, ou alguns subjacente não gerenciado implementação está vazando.

Para a maioria dos vazamentos, os recursos são recuperados quando o processo é finalizado, no entanto, alguns recursos não são sempre recuperados em algumas precisa dos casos, GDI cursor alças são notórias para isso.Claro, se você tiver um mecanismo de comunicação entre processos, de memória alocado em outro processo não seria liberado até que o processo de libera-lo ou termina.

Eu acho que o "o que é um vazamento de memória" e "quais são os efeitos" perguntas foram respondidas bem já, mas eu queria acrescentar mais algumas coisas sobre as outras perguntas...

Como compreender se a sua aplicação de vazamentos

Uma forma interessante é abrir perfmon e adicionar traços para nº de bytes em todas as pilhas e # Gen 2 coleções , em cada caso, procurando, no seu processo.Se o exercício de um determinado recurso faz com que o total de bytes a aumentar, e que a memória permanece alocado após a próxima Gen 2 da coleção, pode-se dizer que o recurso de vazamentos de memória.

Como evitar

Outras boas opiniões foram dadas.Gostaria apenas de acrescentar que, talvez, o mais comumente ignorados causa .NET vazamentos de memória é adicionar manipuladores de eventos para objetos sem removê-los.Um manipulador de eventos ligados a um objeto é uma forma de referência a esse objeto, assim vai evitar coleção, mesmo depois de todas as outras referências desapareceram.Lembre-se sempre de desconectar manipuladores de eventos (usando o -= a sintaxe do C#).

O vazamento de ir embora quando o processo termina, e o que sobre interoperabilidade?

Quando o processo termina, toda a memória mapeada para o espaço de endereço é recuperado pelo sistema operacional, incluindo quaisquer objectos COM servidos a partir de DLLs.Comparativamente, raramente, COM os objetos podem ser servidos a partir de processos separados.Neste caso, quando o processo termina, você ainda pode ser responsável pela memória alocado em qualquer servidor COM processos que você usou.

Gostaria de definir vazamentos de memória como um objeto não liberando toda a memória alocada depois de ter concluído.Eu encontrei isso pode acontecer na sua aplicação, se você estiver usando a API do Windows e COM (i.e.o código não gerido que tem um erro ou não está sendo gerenciada corretamente), no âmbito e em componentes de terceiros.Descobri também não arranjo depois de utilizar determinados objetos, como canetas podem causar o problema.

Eu, pessoalmente, tenho sofrido de Exceções de Memória que pode ser causado, mas não são exclusivas para vazamentos de memória em dot net applications.(OOM também pode vir a fixação de ver A Fixação De Artical).Se você não está recebendo OOM erros ou necessidade de confirmar se é um vazamento de memória fazendo com que ele, em seguida, a única maneira é o perfil do seu aplicativo.

Também gostaria de tentar assegurar o seguinte:

a) Tudo que implementa Idisposable é eliminado através de um bloco finally ou a instrução usando estes incluem pincéis, canetas, etc.(algumas pessoas argumentam para definir tudo para nada além disso)

b)Tudo o que tem um método close é fechado novamente usando por último ou a instrução de uso (apesar de eu ter encontrado a utilizar não feche sempre dependendo se você declarou o objeto fora a instrução de uso)

c)Se você estiver usando o código não gerenciado/API do windows que estas são tratadas corretamente depois.(alguns têm métodos de limpeza para a liberação de recursos)

Espero que isso ajude.

Se você precisa de diagnosticar um vazamento de memória .NET, consulte estes links:

http://msdn.microsoft.com/en-us/magazine/cc163833.aspx

http://msdn.microsoft.com/en-us/magazine/cc164138.aspx

Os artigos descrevem como criar um despejo de memória do processo e como analisá-lo de modo que você possa determinar se o vazamento é gerenciado ou não gerenciado, e se ele é gerido, como descobrir de onde isso está vindo.

A Microsoft também tem uma nova ferramenta para ajudar com a geração de despejos, para substituir o ADPlus, chamado DebugDiag.

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

Usar perfil do CLR da Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en é uma ótima maneira para determinar quais objetos estão segurando memória, o que o fluxo de execução leva à criação desses objetos, e também o monitoramento de objetos que vive, onde no heap (fragmentação, LOH, etc.).

A melhor explicação de como o coletor de lixo funciona em Jeff Richters CLR através de C# livro (Cap.20).Lendo isso dá uma grande base para a compreensão de como os objetos persistem.

Uma das causas mais comuns de enraizamento objetos acidentalmente está ligando eventos outisde uma classe.Se você ligar um evento externo

exemplo:

SomeExternalClass.Changed += new EventHandler(HandleIt);

e se esqueça de desligar quando você eliminar e, em seguida, SomeExternalClass tem uma ref para sua classe.

Como mencionado acima, a SciTech memória profiler é excelente para mostrar que você raízes de objetos que você suspeitar que está a sofrer.

Mas existe também uma forma muito rápida para verificar se um determinado tipo é só usar WnDBG (você pode até mesmo usar isso no VS.NET janela imediata, enquanto em anexo):

.loadby sos mscorwks
!dumpheap -stat -type <TypeName>

Agora fazer algo que você acha que vai vender os objetos do tipo (e.g.fechar uma janela).É útil aqui para ter um botão de depuração em algum lugar que será executado System.GC.Collect() um par de vezes.

Em seguida, executar !dumpheap -stat -type <TypeName> novamente.Se o número de não descer ou não descer tanto quanto você espera, então você tem uma base para outras investigações.(Recebi essa dica de um seminário dado por Ingo Pilão).

Eu acho que em um ambiente gerenciado, um vazamento seria manter a desnecessária referência a um bloco grande de memória em torno.

Por que as pessoas pensam que um vazamento de memória .NET não é o mesmo que qualquer outra fuga?

Um vazamento de memória é quando você conectar a um recurso e não deixá-lo ir.Você pode fazer isso tanto em gerenciados e não gerenciados de codificação.

Respeito .NET, e outras ferramentas de programação, foram idéias sobre a coleta de lixo, e outras maneiras de minimizar situações que irão tornar a sua aplicação vazamento.Mas o melhor método de prevenção de vazamentos de memória é que você precisa entender o seu subjacentes modelo de memória, e como as coisas funciona, na plataforma que você está usando.

Acreditando que a GC e outros magia irá limpar a sua bagunça é o caminho curto para vazamentos de memória, e vai ser difícil de encontrar mais tarde.

Quando a codificação não gerenciado, você normalmente certifique-se de limpar, você sabe que os recursos de que você segure, será sua a responsabilidade de limpar, não o filho do zelador.

Em .NET por outro lado, muita gente acha que o GC vai limpar tudo.Bem, faz algum para você, mas você precisa ter certeza de que é assim..NET dispor um monte de coisas, então você não sabe se você está lidando com um gerenciado ou não de recursos, e você precisa ter certeza de que o que você está lidando com.Manuseio de fontes, recursos GDI, active directory, bancos de dados etc é normalmente coisas que você precisa olhar para fora.

Em termos gerenciados vou colocar no meu pescoço a linha para dizer que ele não vá embora de uma vez o processo é morto/removidos.

Eu vejo muitas pessoas têm esse pensamento, e eu realmente espero que isso vai acabar.Você não pode pedir ao usuário para encerrar o aplicativo para limpar a sua bagunça!Dê uma olhada em um navegador, que pode ser IE, FF, etc, em seguida, abrir, digamos, o Google Reader, deixe-o ficar por alguns dias e veja o que acontece.

Se você, em seguida, abra uma outra aba no navegador, navegar para um site, em seguida, feche a aba que sediou a outra página que fez com que o navegador da fuga, você acha que o navegador irá liberar a memória?Não é assim com o IE.No meu computador o IE facilmente comer 1 GiB de memória em um curto espaço de tempo (cerca de 3 a 4 dias), se eu usar o Google Reader.Alguns newspages são ainda piores.

Eu acho que em um ambiente gerenciado, um vazamento seria a manter um desnecessário referência a um pedaço grande de memória em torno.

Absolutamente.Também, não usando .Método Dispose() no objeto descartável, quando apropriado, pode causar mem vazamentos.A maneira mais fácil de fazer isso é com um usando o bloco, pois ela executa automaticamente .Dispose() no final:

StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
    //do some stuff
}

E, se você criar uma classe que está a utilizar objetos não gerenciados, se você não estiver implementação IDisposable corretamente, você poderia estar causando vazamentos de memória para a sua classe de usuários.

Todos os vazamentos de memória são resolvidos pelo término do programa.

Vazamento de memória e o Sistema Operacional pode decidir resolver o problema a seu favor.

Eu concordo com o Bernardo no .líquido que mem vazamento seria.

Você poderia perfil de seu aplicativo para ver o consumo de memória, e determinar que, se a sua gestão de uma grande quantidade de memória quando ele deve não ser você poderia dizer que tem um vazamento.

Em termos gerenciados eu vou colocar o meu pescoço em linha para dizer que ele não vá para longe uma vez que o processo é morto/removidos.

O código não gerenciado é o seu próprio animal e se um vazamento existe dentro dele, ele vai seguir um padrão de mem.vazamento de definição.

Também tenha em mente que .NET tem dois montes, sendo uma pilha de objectos grandes.Eu acredito objetos de cerca de 85k ou maior são colocados na pilha.Esta pilha tem um ciclo de vida diferente de regras do que o normal pilha.

Se você está a criação de grandes estruturas de memória (Dicionário ou Lista), isso seria prudente ir de pesquisa de que as regras são.

Na medida recuperar a memória no processo de rescisão, a menos que a sua execução Win98 ou equivalentes, tudo o que é lançado de volta para o sistema operacional em caso de rescisão.As únicas exceções são as coisas que são abertos processo cruzado e outro processo ainda tem o recurso de abrir.

COM Objetos pode ser complicado, tho.Se você sempre usar o IDispose padrão, você estará seguro.Mas eu tenho alguns assemblies de interoperabilidade que implementam IDispose.A chave aqui é chamada de Marshal.ReleaseCOMObject quando você é feito com ele.Os Objetos COM ainda utilizar COM padrão de contagem de referência.

Eu encontrei .Net Memória Profiler uma ajuda muito boa quando encontrar vazamentos de memória no .Líquida.Não é gratuito como o Microsoft perfil do CLR, mas é mais rápida e mais para o momento, na minha opinião.Um

Uma definição é: Não consegue libertar-se inacessível memória, que não pode ser atribuído ao novo processo durante a execução de alocação de processo.Ele pode em grande parte ser curado usando GC técnicas ou detectados por ferramentas automatizadas.

Para mais informações, por favor visite http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top