No código C / C ++ não gerenciado, quais são as práticas recomendadas para detectar vazamentos de memória? E diretrizes de codificação para evitar? (Como se fosse assim tão simples;)
Usamos um pouco de maneira boba no passado: ter um incremento no contador para cada chamada de alocação de memória e decremento durante a liberação. No final do programa, o valor do contador deve ser zero.
Eu sei que essa não é uma ótima maneira e existem algumas capturas. (Por exemplo, se você estiver liberando memória que foi alocada por uma chamada de API da plataforma, sua contagem de alocação não corresponderá exatamente à sua contagem de liberação. Obviamente, incrementamos o contador ao chamar as chamadas de API que alocam memória).
Espero suas experiências, sugestões e talvez algumas referências a ferramentas que simplificam isso.
fonte
Respostas:
Se o seu código C / C ++ é portátil para * nix, poucas coisas são melhores que o Valgrind .
fonte
Se você estiver usando o Visual Studio, a Microsoft fornecerá algumas funções úteis para detectar e depurar vazamentos de memória.
Gostaria de começar com este artigo: https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.140).aspx
Aqui está o rápido resumo desses artigos. Primeiro, inclua estes cabeçalhos:
Então você precisa chamar isso quando o seu programa sair:
Como alternativa, se o seu programa não sair sempre no mesmo local, você pode chamar isso no início do programa:
Agora, quando o programa sair, todas as alocações que não foram liberadas serão impressas na Janela de Saída, juntamente com o arquivo em que foram alocadas e a ocorrência da alocação.
Essa estratégia funciona para a maioria dos programas. No entanto, torna-se difícil ou impossível em certos casos. O uso de bibliotecas de terceiros que fazem alguma inicialização na inicialização pode fazer com que outros objetos apareçam no despejo de memória e dificultar o rastreamento de seus vazamentos. Além disso, se alguma de suas classes tiver membros com o mesmo nome de qualquer uma das rotinas de alocação de memória (como malloc), as macros de depuração do CRT causarão problemas.
Existem outras técnicas explicadas no link do MSDN mencionado acima que também podem ser usadas.
fonte
Em C ++: use RAII. Ponteiros inteligentes gostam
std::unique_ptr
,std::shared_ptr
,std::weak_ptr
são seus amigos.fonte
Como desenvolvedor de C ++, aqui estão algumas diretrizes:
Quanto à detecção de vazamentos de memória pessoalmente, sempre usei o Visual Leak Detector e acho muito útil.
fonte
Eu uso o DevStudio há muitos anos e sempre me surpreende quantos programadores não sabem sobre as ferramentas de análise de memória disponíveis nas bibliotecas de tempo de execução de depuração. Aqui estão alguns links para começar:
Rastreando solicitações de alocação de heap - especificamente a seção Números de solicitação de alocação exclusivos
_CrtSetDbgFlag
_CrtSetBreakAlloc
Obviamente, se você não estiver usando o DevStudio, isso não será particularmente útil.
fonte
Estou surpreso que ninguém tenha mencionado o DebugDiag para Windows OS.
Ele funciona em versões de lançamento e até no site do cliente.
(Você só precisa manter os PDBs da versão de lançamento e configurar o DebugDiag para usar o servidor de símbolos públicos da Microsoft)
fonte
O Visual Leak Detector é uma ferramenta muito boa, embora não suporte as chamadas nos tempos de execução do VC9 (MSVCR90D.DLL, por exemplo).
fonte
O Microsoft VC ++ no modo de depuração mostra vazamentos de memória, embora não mostre onde estão os vazamentos.
Se você estiver usando C ++ você sempre pode evitar o uso de novo explicitamente: você tem
vector
,string
,auto_ptr
(pré C ++ 11; substituído porunique_ptr
em C ++ 11),unique_ptr
(C ++ 11) eshared_ptr
(C ++ 11) em seu arsenal.Quando new for inevitável, tente ocultá-lo em um construtor (e ocultar delete em um destruidor); o mesmo funciona para APIs de terceiros.
fonte
Existem várias bibliotecas "malloc" substitutas por aí que permitem que você chame uma função no final e ela informa sobre toda a memória não liberada e, em muitos casos, quem a mallocou (ou foi recém-introduzida) em primeiro lugar .
fonte
Se você estiver usando o MS VC ++, recomendo esta ferramenta gratuita no codeproject: leakfinder de Jochen Kalmbach.
Você simplesmente adiciona a classe ao seu projeto e chama
antes e depois do código que você deseja verificar se há vazamentos.
Depois de criar e executar o código, Jochen fornece uma ferramenta GUI pura, na qual é possível carregar o arquivo .xmlleaks resultante e navegar pela pilha de chamadas onde cada vazamento foi gerado para procurar a linha de código incorreta.
O PurifyPlus da Rational (agora de propriedade da IBM) ilustra vazamentos de maneira semelhante, mas acho a ferramenta de rastreador de vazamentos realmente mais fácil de usar, com o bônus de não custar vários milhares de dólares!
fonte
Eu nunca o usei, mas meus amigos C me dizem Purify .
fonte
Se você estiver usando o Visual Studio, pode valer a pena examinar o Verificador de limites . Não é gratuito, mas tem sido incrivelmente útil para encontrar vazamentos no meu código. Ele não apenas faz vazamentos de memória, mas também vazamentos de recursos GDI, erros de uso do WinAPI e outras coisas. Ele até mostra onde a memória vazada foi inicializada, facilitando a localização do vazamento.
fonte
Eu acho que não há uma resposta fácil para essa pergunta. Como você realmente pode abordar esta solução depende de seus requisitos. Você precisa de uma solução multiplataforma? Você está usando new / delete ou malloc / free (ou ambos)? Você está realmente procurando apenas "vazamentos" ou deseja uma melhor proteção, como a detecção de excedentes de buffer (ou underruns)?
Se você estiver trabalhando no lado do Windows, as bibliotecas do MS debug runtime têm algumas funcionalidades básicas de detecção de depuração e, como outra já apontou, existem vários wrappers que podem ser incluídos na sua fonte para ajudar na detecção de vazamentos. Encontrar um pacote que possa funcionar com new / delete e malloc / free obviamente oferece mais flexibilidade.
Não sei o suficiente sobre o lado unix para fornecer ajuda, embora mais uma vez outros o tenham.
Mas, além da detecção de vazamento, existe a noção de detecção de corrupção de memória via saturação de buffer (ou saturação). Esse tipo de funcionalidade de depuração é mais difícil que a simples detecção de vazamentos. Esse tipo de sistema também é mais complicado se você estiver trabalhando com objetos C ++, pois as classes polimórficas podem ser excluídas de várias maneiras, causando dificuldade na determinação do verdadeiro ponteiro base que está sendo excluído. Não conheço um bom sistema "gratuito" que faça uma proteção decente para excedentes. nós escrevemos um sistema (multiplataforma) e achamos bastante desafiador.
fonte
Eu gostaria de oferecer algo que usei em alguns momentos no passado: um verificador de vazamentos rudimentar, que é no nível da fonte e bastante automático. Estou denunciando isso por três razões:
Você pode achar util.
Embora seja um pouco errado, não deixo isso me envergonhar.
Mesmo que esteja vinculado a alguns ganchos win32, isso deve ser fácil de aliviar.
Há coisas que você deve ter cuidado ao usá-la: não faça nada que precise se apoiar
new
código subjacente, tenha cuidado com os avisos sobre casos que podem faltar no topo do leakcheck.cpp, perceba que se você ligar (e corrija quaisquer problemas com) o código que faz o despejo de imagens, você pode gerar um arquivo enorme.O design visa permitir que você ligue e desligue o verificador sem recompilar tudo o que inclui seu cabeçalho. Inclua leakcheck.h onde deseja rastrear a verificação e reconstruir uma vez. Depois disso, compile leakcheck.cpp com ou sem LEAKCHECK # define e, em seguida, vincule novamente para ativá-lo e desativá-lo. A inclusão de unleakcheck.h o desativará localmente em um arquivo. Duas macros são fornecidas: CLEARALLOCINFO () evitará relatar o mesmo arquivo e linha de forma inadequada quando você percorrer o código de alocação que não incluiu leakcheck.h. ALLOCFENCE () apenas descarta uma linha no relatório gerado sem fazer nenhuma alocação.
Novamente, lembre-se de que não utilizo isso há algum tempo e você pode precisar trabalhar um pouco. Estou falando disso para ilustrar a ideia. Se houver interesse suficiente, eu estaria disposto a elaborar um exemplo, atualizando o código no processo e substituindo o conteúdo da URL a seguir por algo mais agradável que inclua uma lista decentemente colorida de sintaxe.
Você pode encontrá-lo aqui: http://www.cse.ucsd.edu/~tkammeye/leakcheck.html
fonte
Para Linux: tente Google Perftools
Existem muitas ferramentas que fazem contagem similar de alocação / livre, os profissionais do Goolge Perftools:
fonte
A melhor defesa contra vazamentos é uma estrutura de programa que minimiza o uso de malloc. Isso não é apenas bom do ponto de vista de programação, mas também melhora o desempenho e a capacidade de manutenção. Eu não estou falando sobre o uso de outras coisas no lugar do malloc, mas em termos de reutilização de objetos e de manter abas muito explícitas em todos os objetos que estão sendo passados ao invés de alocar à vontade, como costuma ser usado em idiomas com coletores de lixo como Java.
Por exemplo, um programa em que trabalho tem um monte de objetos de quadro que representam dados de imagem. Cada objeto de quadro possui sub-dados, liberados pelo destruidor do quadro. O programa mantém uma lista de todos os quadros alocados e, quando precisar de um novo, verifica uma lista de objetos de quadro não utilizados para ver se é possível reutilizar um existente, em vez de alocar um novo. No desligamento, ele apenas percorre a lista, liberando tudo.
fonte
Eu recomendaria o uso do Memory Validator partir da verificação do software. Essa ferramenta provou ser uma ajuda inestimável para me ajudar a rastrear vazamentos de memória e melhorar o gerenciamento de memória dos aplicativos em que estou trabalhando.
Uma ferramenta muito completa e rápida.
fonte
Você está contando as alocações e liberações interpolando suas próprias funções syscall que gravam as chamadas e depois passam a chamada para a função real?
Essa é a única maneira de controlar as chamadas originadas no código que você não escreveu.
Dê uma olhada na página de manual do ld.so. Ou ld.so.1 em alguns sistemas.
Faça também o Google LD_PRELOAD e você encontrará alguns artigos interessantes explicando a técnica no site www.itworld.com.
fonte
Pelo menos para o MS VC ++, a biblioteca C Runtime possui várias funções que eu achei úteis no passado. Verifique a ajuda do MSDN para as
_Crt*
funções.fonte
O mmgr de Paul Nettle é uma das minhas ferramentas favoritas de longa data. Você inclui mmgr.h nos arquivos de origem, define TEST_MEMORY e ele fornece um arquivo de texto cheio de problemas de memória que ocorreram durante a execução do seu aplicativo.
fonte
Diretriz geral de codificação:
fonte
As ferramentas de depuração de memória valem seu peso em ouro, mas, ao longo dos anos, descobri que duas idéias simples podem ser usadas para impedir que a maioria dos vazamentos de memória / recursos seja codificada em primeiro lugar.
Escreva o código de liberação imediatamente após escrever o código de aquisição para os recursos que você deseja alocar. Com esse método, é mais difícil "esquecer" e, em certo sentido, obriga a pensar seriamente no ciclo de vida dos recursos sendo usados antecipadamente, e não como um aparte.
Use o retorno o mais moderadamente possível. O que é alocado deve ser liberado apenas em um local, se possível. O caminho condicional entre a aquisição do recurso e a liberação deve ser projetado para ser o mais simples e óbvio possível.
fonte
No topo desta lista (quando a li) estava o valgrind. O Valgrind é excelente se você conseguir reproduzir o vazamento em um sistema de teste. Eu usei com grande sucesso.
E se você acabou de perceber que o sistema de produção está vazando no momento e você não tem idéia de como reproduzi-lo em teste? Alguma evidência do que está errado é capturada no estado desse sistema de produção e pode ser suficiente para fornecer uma visão de onde está o problema, para que você possa reproduzi-lo.
É aí que a amostra de Monte Carlo entra em cena. Leia o artigo do blog de Raymond Chen, “O jeito do pobre homem de identificar vazamentos de memória” e confira minha implementação (assume o Linux, testado apenas em x86 e x86-64)
http://github.com/tialaramex/leakdice/tree/master
fonte
Trabalhando no sistema operacional de telefones celulares da Motorola, invadimos a biblioteca de alocação de memória para observar todas as alocações de memória. Isso ajudou a encontrar muitos problemas com alocações de memória. Como a prevenção é melhor do que remediar , eu recomendaria o uso de ferramentas de análise estática como Klockwork ou PC-Lint
fonte
lint
. Ele tem muitas verificações específicas para C ++, que o afaik splint não possui. Veja o link na resposta (que renomei de Lint para PC-Lint).Valgrind é uma boa opção para Linux. No MacOS X, você pode ativar a biblioteca MallocDebug, que possui várias opções para depurar problemas de alocação de memória (consulte a página de manual do malloc, a seção "AMBIENTE" possui os detalhes relevantes). O OS X SDK também inclui uma ferramenta chamada MallocDebug (geralmente instalada em / Developer / Applications / Performance Tools /) que pode ajudá-lo a monitorar o uso e os vazamentos.
fonte
Detectar:
Depurar CRT
Evitar:
Ponteiros inteligentes, boehm GC
fonte
Uma boa substituição de malloc, calloc e reallloc é o rmdebug, é bem simples de usar. É muito mais rápido fazer valgrind, para que você possa testar seu código extensivamente. É claro que ele tem algumas desvantagens, uma vez que você encontrou um vazamento, provavelmente ainda precisará usar o valgrind para descobrir onde o vazamento aparece e você só pode testar mallocs diretamente. Se uma lib vazar porque você a usa incorretamente, o rmdebug não a encontrará.
http://www.hexco.de/rmdebug/
fonte
A maioria dos criadores de perfil de memória desacelera meu aplicativo Windows grande e complexo até o ponto em que os resultados são inúteis. Há uma ferramenta que funciona bem para encontrar vazamentos no meu aplicativo: UMDH - http://msdn.microsoft.com/en-us/library/ff560206%28VS.85%29.aspx
fonte
Mtrace parece ser o padrão embutido no linux. Os passos são:
MALLOC_TRACE = / tmp / mtrace.dat
export MALLOC_TRACE;
mtrace your_prog_exe_name /tmp/mtrace.dat
(Eu tive que instalar o script mtrace perl primeiro no meu sistema fedora com o yum install glibc_utils )
fonte