Pergunta

Estou tendo problemas com um vazamento de memória lenta no meu modo misto C ++ / aplicação CLR .NET.

(bibliotecas estáticas nativas É de C ++ ligados em um VS2008 C ++ / app CLR Windows Forms com o "/ clr" configuração do compilador)

O comportamento típico: aplicativo começa a usar 30 MB (memória privada). Então vazamentos slowish memória, digamos, um MB a cada hora durante a execução sob carga pesada simulado. Isso simula o aplicativo estar vivo por dias ou semanas.

Eu tentei usar várias ferramentas para rastrear vazamentos de memória, incluindo tanto o material CRT depuração que vem com as libs o Visual Studio CRT. Eu também usou uma ferramenta de detecção de vazamento comercial ( "Validador de memória").

Ambos os relatórios vazamentos de memória insignificantes no desligamento (algumas entradas menores que equivalem a poucos KB que eu não estou preocupado com). Além disso, eu posso ver ao executar que a memória tracked não parece valor a que muito (assim eu não acredito que é apenas memória que está sendo realizada e liberado somente na saída app). Recebo cerca de 5 MB de memória listada (de um total de> 30 MB).

A ferramenta (Memory Validador) está configurado para rastrear todo o uso de memória (incluindo malloc, alocação de memória nova, virtual e um monte de outros tipos de alocação de memória). Basicamente, cada cenário para que a memória para a faixa foi selecionada.

Os relatórios de imagem NET que está usando cerca de 1,5 MB de memória (de perfmon).

Aqui está um pouco final de informação: temos uma versão do aplicativo que funciona como um aplicativo nativo console (puramente nativa - não CLR em tudo). Isso é 95% o mesmo que o modo misto exceto sem o material UI. Este não parece vazar memória em tudo, e picos em torno de 5MB bytes privados.

Então, basicamente o que eu estou tentando passar aqui é que eu não acho que nenhum do código nativo está vazando memória.

Outra peça do quebra-cabeça: Achei isso que se refere a vazamentos de memória em aplicativos de modo misto quando o direcionamento 2.0 quadro (que eu sou): http://support.microsoft.com/kb/961870

Infelizmente, os detalhes são irritantemente escassa por isso não tenho certeza se é relevante. Eu tentei alvejando 3,5 estrutura, em vez de 2,0, mas ainda tinha o mesmo problema (talvez eu não fizer isso direito).

Alguém tem alguma sugestão?

Algumas coisas que podem me ajudar:

  • Há algum outro tipo de alocações de memória que eu não estou rastreando?
  • Como é que os números não somam? Recebo 5 MB de uso de memória CRT, 1,5 MB de memória .NET Então como é que os usos toda app 30MB bytes privados? É que tudo amarrado no .NET framework? Por que não vejo estes na ferramenta de vazamento? o .NET framework não aparecerá como uma espécie de memória alocada?
  • Quaisquer outras ferramentas de detecção de fugas que funcionam bem com aplicativos modo misto?

Obrigado por qualquer ajuda

John

Foi útil?

Solução

OK eu finalmente encontrei o problema.

Foi causado por uma configuração incorreta para / EH (Manipulação de exceção).

Basicamente, com mistos aplicativos modo .NET, você precisa fazer libs certeza que todos ligados estaticamente são compilados com / EHa em vez do padrão / EHS.

(O aplicativo em si também deve ser compilado com / EHa, mas este é um dado -.. O compilador irá relatar erro se você não usá-lo O problema é quando você ligar em outras bibliotecas nativas estáticos)

O problema é que as exceções capturadas no bit gerenciado do aplicativo, que foram jogados dentro de bibliotecas nativas compilados com / EHS acabam por não lidar com a exceção corretamente. Destruidores para objetos C ++ não são então chamados corretamente.

No meu caso, isso só ocorreu em um lugar raro, portanto, por isso que me levou séculos para local.

Outras dicas

Como Spence estava dizendo, mas para C ++ / CLI;) ....

Para qualquer objeto que você está usando em C ++ / CLI, se você criar mais esse objeto de de C código ++, você deve tentar seymantics alocação uso de pilha, mesmo que este é um mágico compilador tipo de coisa, é capaz de configurar o __try aninhada {} {} __finally declarações você pode estar acostumado a usar a partir do código nativo (que é a configuração-los em uma maneira de não perder uma chamada para Descarte).

de Nish artigo no projeto de código aqui em C semântica alocação ++ / pilha CLI é muito bom e se aprofunda sobre como emular usando {}.

Você também deve certificar-se de excluir qualquer objeto que implment IDisposable como você não pode chamar Dispose em C ++ / CLI, de exclusão faz isso para você, se você não usar a semântica pilha ..

Eu costumo chamar Close me em Streams e tentar nullptr atribuir quando estou acabado com objetivo de, apenas no caso.

Você também pode querer verificar para fora este artigo sobre problemas de memória , perticularly sobre assinantes do evento, se você está atribuindo o evento de que seus objetos, você pode estar vazando ...

Como um último recurso (ou talvez primeiro :), uma coisa que tenho feito no passado é fazer uso da API CLR Profiler, aqui é um outro artigo sobre como fazer isso, escritor do autor (Jay Hilyard) tem um exemplo que as respostas;

  • De cada tipo .NET que é usado, como muitas instâncias de objetos estão sendo alocados?
  • Como grande são as instâncias de cada tipo?
  • O notificações que o GC fornecer como ela vai através de uma coleta de lixo eo que você pode descobrir?
  • Quando faz o GC recolher as instâncias de objetos?

Caso você obtenha uma ideia melhor do que alguns profiler mercadoria, tenho notado que eles podem ser ocasionalmente enganosa dependendo do seu porofile alocação (btw. Atente para grandes questões objeto heap,> ~ objetos 83KB são especialmente tratadas, em que caso, eu recomendo, ficando fora de heap de objeto grande:.)

Dada seus comentários, algumas coisas mais ...

Eu publiquei antes sobre carga de imagem não está cobrando quota ou qualquer outra estatística disernable, o que isso significa que você pode precisar para rastrear alguns alça ou loader questão (ver bloqueio do carregador eventualmente), mas antes disso, você pode tentar definição Regiões algum Constrained Execução , eles podem trabalhar maravilhas, mas também são, infelizmente, difícil de retro-fit em código não-puro.

Esta recente MSDN Mag , artigo documento é um monte de perfmon sperlunking memória tipo (followup para este mais velho ).

do VS Perf Blog , eles mostram como usar SOS no estúdio visual, que pode ser útil, para rastrear, posts relacionados de rouge DLL também são bons.

Blog do Maoni Stephen e empresa , ele disse de que ele está na equipe perf, mas essencialmente 100% de seus posts são em relação ao GC tanto assim ele pode, assim que escrevi -lo.

Rick Byers é um dev com a equipe de diagnóstico CLR, muitos de seu blog -buddies também sãoboa fonte de, no entanto, gostaria de sugerir fortemente também referindo-se ao muito novo dev / diagnósticos fórum. Eles recentemente expandiu o escopo de suas discussões.

cobertura de código Ferramentas e traçando muitas vezes podem ajudar, para lhe dar uma visão geral do que está realmente em execução.

(specically, aqueles perticular stat pode não ser o que lhe dá uma visão global do que está plauging seu código, posso dizer que, recentemente, eu descobri (mesmo com binários .net4beta, o profiler de esta empresa , é muito bom, ele é capaz de derivar das fugas de nativos / gerido a partir de sua traços perfil, traz para você de volta para as linhas de origem exatas (mesmo otimizado, muito agradável (e tem um julgamento 30 dias)))).

Boa sorte !! Espero que alguma desta ajuda, é apenas fresco em minha mente, como eu estou fazendo muito do mesmo trabalho agora;)

Experimente: DebugDiags .
Depois de gerar alguns despejos de memória, ele vai te dar um bom verão do que memória foi alocada, e dependendo de encontrar o seu APO da, pode dizer por quem foi alocado.

Você pode ter um vazamento de referência, olhar para ANTS profiling software. Formigas Profiler

Um vazamento de referência é o equivalente .net de um vazamento de memória, você mantém referências a um objeto que o impede de ser lixo coletado, e assim você memória em uso começa a subir.

É possível que você perdeu alguns trituradores, pode acontecer se o seu usando GDI + e muitas outras APIs.

Se o seu executar a ferramenta de análise estática FXCop tem uma regra para verificar se você chamada dispose (ou usado os "usando") declarações sobre os objetos que fornecem a interface. Na Net se uma função usa código não gerenciado que geralmente fornecem um descarte ou método close para você para não vazar o recurso / memória.

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