Localizando vazamentos de memória usando a biblioteca do CRT

This topic applies to:

Edition

Visual Basic

C#

F#

C++

Web Developer

Express

O tópico não é aplicável O tópico não é aplicável O tópico não é aplicável

Native only

O tópico não é aplicável

Pro, Premium e Ultimate

O tópico não é aplicável O tópico não é aplicável O tópico não é aplicável

Native only

O tópico não é aplicável

Vazamentos de memória, definidos como a falha de desalocar corretamente a memória que foi anteriormente alocada são mais sutis e difíceis de detectar bugs nos aplicativos em C/C++. Um vazamento de memória pequeno pode não ser notado em primeiro lugar, mas ao longo do tempo, um vazamento de memória progressivo pode causar sintomas que variam de desempenho reduzido para travamento, quando o aplicativo é executado fora da memória. Pior ainda, um aplicativo de vazamento usa toda a memória disponível pode causar outro aplicativo falhe, criando confusão qual aplicativo é responsável. Mesmo que aparentemente vazamentos de memória inofensivo talvez sintomáticos de outros problemas que devem ser corrigidos.

O Visual Studio depurador e bibliotecas C Run-Time (CRT) fornecem os meios para detectar e identificar vazamentos de memória.

Ativar detecção de vazamento de memória

As principais ferramentas para detecção de vazamentos são o depurador e o tempo de execução bibliotecas CRT (C) de memória de funções de heap de depuração.

Para habilitar as funções de heap de depuração, inclua as seguintes instruções no programa:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

Para as funções de CRT funcione corretamente, o #include instruções devem seguir a ordem mostrada aqui.

Incluindo mapas de crtdbg.h a malloc e o livre funções para suas versões de depuração, _malloc_dbg e free, que controla a alocação de memória e desalocação. Esse mapeamento ocorre apenas em compilações de depuração, que têm _DEBUG. Compilações lançadas comum de usar malloc e free funções.

O #define instrução mapeia uma versão base das funções CRT heap para a versão de depuração correspondente. Se você omitir o #define de instrução, o despejo de vazamento de memória serão menos detalhado.

Depois que você habilitou as funções de heap de depuração usando essas instruções, você pode colocar uma chamada para _CrtDumpMemoryLeaks antes de um ponto de saída do aplicativo para exibir um relatório de vazamento de memória quando sai de seu aplicativo:

_CrtDumpMemoryLeaks();

Se seu aplicativo tiver várias saídas, você não precisará fazer manualmente uma chamada para _CrtDumpMemoryLeaks em cada ponto de saída. Uma chamada para _CrtSetDbgFlag no início do seu aplicativo fará com que uma chamada automática para _CrtDumpMemoryLeaks em cada ponto de saída. Você deve definir os campos de bit dois mostrados aqui:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

Por padrão, _CrtDumpMemoryLeaks gera o relatório de vazamento de memória para o Debug o painel da saída janela. Você pode usar _CrtSetReportMode para redirecionar o relatório para outro local.

Se você usar uma biblioteca, a biblioteca pode redefinir a saída para outro local. Nesse caso, você pode definir o local de saída para o saída janela, conforme mostrado aqui:

_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

Interpretar o relatório de vazamento de memória

Se o seu aplicativo não define _CRTDBG_MAP_ALLOC, _CrtDumpMemoryLeaks exibe um relatório de vazamento de memória que é semelhante à seguinte:

Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Se seu aplicativo define _CRTDBG_MAP_ALLOC, o relatório de vazamento de memória tem esta aparência:

Detected memory leaks!
Dumping objects ->
C:\PROGRAM FILES\VISUAL STUDIO\MyProjects\leaktest\leaktest.cpp(20) : {18} 
normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

A diferença é que o segundo relatório mostra o nome do arquivo e o número da linha onde a memória com vazamento primeiro alocada.

Se você definir _CRTDBG_MAP_ALLOC ou não, o vazamento de memória relatório exibir as seguintes informações:

  • O número de alocação de memória, que é 18 neste exemplo

  • O o tipo de bloco, que é normal neste exemplo.

  • O local de memória hexadecimal, o que é 0x00780E80 neste exemplo.

  • O tamanho de bloco, 64 bytes neste exemplo.

  • Os primeiros 16 bytes de dados no bloco, em formato hexadecimal.

O relatório de vazamento de memória identifica um bloco de memória como normal, o cliente ou CRT. A Bloco normal comum memória alocada pelo seu programa. A Bloco de cliente é um tipo especial de bloco de memória usado por programas MFC para objetos que requerem um destruidor. O MFC new operador cria um bloco normal ou em um bloco de cliente, conforme apropriado para o objeto que está sendo criado. A Bloco de CRT é alocada da biblioteca CRT para seu próprio uso. A biblioteca do CRT manipula a desalocação para esses blocos. Portanto, é improvável que você verá esses no relatório de vazamento de memória, a menos que algo é significativamente errado, por exemplo, da biblioteca CRT está corrompida.

Existem dois outros tipos de blocos de memória que nunca aparecem nos relatórios de vazamento de memória. A bloco livre é a memória que foi lançada. Isso significa que ele não é vazarem, por definição. Um Ignorar o bloco é a memória que você marcou explicitamente para excluí-la do relatório de vazamento de memória.

Essas técnicas funcionam para a memória alocada usando a CRT padrão malloc função. Se o seu programa aloca memória usando o C++ new operador, no entanto, você precisará redefinir new se você deseja ver os números de arquivo e a linha no relatório de vazamento de memória. Você pode fazer isso com um bloco de código que tem esta aparência:

#ifdef _DEBUG
   #ifndef DBG_NEW
      #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
      #define new DBG_NEW
   #endif
#endif  // _DEBUG

Definir pontos de interrupção em um número de alocação de memória

O número de alocação de memória informa quando um bloco de memória com vazamento foi alocado. Um bloco com um número de alocação de memória de 18, por exemplo, é o bloco de 18 de memória alocado durante a execução do aplicativo. O relatório de CRT conta todas as alocações de bloco de memória durante a execução. Isso inclui as alocações da biblioteca CRT e outras bibliotecas como, por exemplo, MFC. Portanto, um bloco com um número de alocação de memória de 18 talvez não seja o bloco de memória 18 alocado pelo seu código. Normalmente, ele não será.

Você pode usar o número de alocação para definir um ponto de interrupção na alocação de memória.

Para definir um ponto de interrupção de alocação de memória usando a janela de inspeção

  1. Definir um ponto de interrupção perto do início do seu aplicativo e inicie o aplicativo.

  2. Quando o aplicativo for interrompido no ponto de interrupção, o Watch janela.

  3. No Watch janela, digite _crtBreakAlloc na nome coluna.

    Se você estiver usando a versão DLL multithread da biblioteca CRT (opção /MD), inclua o operador de contexto: {,,msvcr100d.dll}_crtBreakAlloc

  4. Pressione retornar.

    O depurador avalia a chamada e coloca o resultado na valor coluna. Este valor será – 1 se você não definiu nenhum ponto de interrupção em alocações de memória.

  5. No valor coluna, substitua o valor mostrado com o número de alocação de alocação de memória, onde você deseja quebrar.

Depois de definir um ponto de interrupção em um número de alocação de memória, você pode continuar a depuração. Tenha cuidado ao executar o programa sob as mesmas condições como a execução anterior, para que não altera a ordem de alocação de memória. Quando seu programa interrompido na alocação de memória especificado, você pode usar o Call Stack janela e outras janelas do depurador para determinar as condições sob as quais a memória foi alocada. Em seguida, você pode continuar a execução para observar o que acontece com o objeto e determinar por que ele não corretamente desalocado.

A definição de um ponto de interrupção de dados no objeto também pode ser útil. For more information, see Como: Definir um ponto de interrupção de dados (somente nativo).

Você também pode definir pontos de interrupção de alocação de memória no código. Há duas maneiras de fazer isso:

_crtBreakAlloc = 18;

or:

_CrtSetBreakAlloc(18);

Comparando os estados de memória

Outra técnica para localizar vazamentos de memória envolve tirar instantâneos de estado de memória do aplicativo em momentos importantes. Um instantâneo do estado de memória em um determinado ponto no seu aplicativo, criar um _CrtMemState estruturar e passá-lo para o _CrtMemCheckpoint função. Esta função preenche a estrutura com um instantâneo do estado atual de memória:

_CrtMemState s1;
_CrtMemCheckpoint( &s1 );

_CrtMemCheckpointpreenche a estrutura com um instantâneo do estado atual de memória.

Para gerar o conteúdo de um _CrtMemState estrutura, passar a estrutura para o _ CrtMemDumpStatistics função:

_CrtMemDumpStatistics( &s1 );

_ CrtMemDumpStatisticsgera um despejo do estado de memória tem esta aparência:

0 bytes in 0 Free Blocks.
0 bytes in 0 Normal Blocks.
3071 bytes in 16 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 3071 bytes.
Total allocations: 3764 bytes.

Para determinar se um vazamento de memória ocorreu em uma seção de código, você pode tirar instantâneos de estado de memória, antes e após a seção e, em seguida, use _ CrtMemDifference para comparar dois estados:

_CrtMemCheckpoint( &s1 );
// memory allocations take place here
_CrtMemCheckpoint( &s2 );

if ( _CrtMemDifference( &s3, &s1, &s2) )
   _CrtMemDumpStatistics( &s3 );

_CrtMemDifferencecompara os estados de memória s1 e s2 e retorna um resultado em (s3) ou seja, a diferença de s1 e s2.

Uma técnica para localizar vazamentos de memória começa colocando _CrtMemCheckpoint chamadas no início e no final do seu aplicativo, em seguida, usando _CrtMemDifference para comparar os resultados. Se _CrtMemDifference mostra a um vazamento de memória, você pode adicionar mais _CrtMemCheckpoint chamadas para dividir seu programa usando uma pesquisa binária até que tenha isolado o código-fonte do vazamento.

Falsos positivos

Em alguns casos, _CrtDumpMemoryLeaks pode dar indicações falsas de vazamentos de memória. Isso pode ocorrer se você usar uma biblioteca de marca de alocações internas como _NORMAL_BLOCKs em vez de _CRT_BLOCKs ou _CLIENT_BLOCKs. Nesse caso, _CrtDumpMemoryLeaks não é capaz de dizer a diferença entre as alocações de usuário e as alocações de biblioteca interna. Se os destrutores globais para alocações de biblioteca executado após o ponto onde você chamar _CrtDumpMemoryLeaks, cada alocação interno de biblioteca é reportada um vazamento de memória. Versões mais antigas do Standard Template Library, anteriores à Visual Studio.NET, o que causou _CrtDumpMemoryLeaks para relatar como falso positivos, mas isso foi corrigido nas versões recentes.

Consulte também

Conceitos

Segurança do Depurador

Outros recursos

A pilha de depuração do CRT

Depuração de código nativo

A detecção de vazamentos de memória no MFC