Depurando Vazamentos de Memória com kbmMW

Monitoramento de Uso de Memória com kbmMW

As versões atuais do kbmMW incluem funcionalidades como registro de logs, auditorias e rastreamento de pilha para tratamanto de exceções em tempo de execução. Recentemente, foi adicionado suporte para depuração de uso de memória. Esses recursos são úteeis em qualquer aplicativo, mesmo naqueles que não utilizam outras bibliotecas do kbmMW.

Enquanto ferramentas como o FastMM detectam vazamentos apenas em alocações padrão (ex.: GetMem), o kbmMW monitora também alocações via APIs do Windows, como VirtualAlloc, GlobalAlloc, LocalAlloc e HeapAlloc. Mesmo sem o FastMM, o depurador do kbmMW permite registrar estatísticas de memória em tempo reeal.

Configuração Inicial

Para habilitar o depurador de memória, adicione a unidade kbmMWDebugMemory à cláusula uses do seu aplicativo. Além disso, defina as seguintes diretivas no arquivo kbmMWConfig.inc:


{$DEFINE KBMMW_SUPPORT_DEBUGMEMORY}
{$DEFINE KBMMW_INSTALL_DEBUGMEMORY_HANDLERS}

Se KBMMW_SUPPORT_DEBUGMEMORY não estiver definida, nenhuma funcionalidade de depuração de memória estará disponível. Se KBMMW_INSTALL_DEBUGMEMORY_HANDLERS for omitida, os hooks de memória não serão instalados automaticamente, mesmo que as funções existam.

Com as definições ativadas e a unidade incluída, o kbmMW instalará automaticamente os hooks de depuração. Para obter rastreamentos de pilha detalhados, compile o aplicativo com informações de depuração (ex.: arquivos TDS ou MAP).

Conceitos Fundamentais

O kbmMW intercepta alocações de memória do Borland (objeto/string/memória), além de métodos do Windows (Virtual, Global, Local e Heap). Cada alocação recebe um identificador único de 64 bits, que pode ser usado para rastrear operações entre dois pontos no tempo, denominados checkpoints.

Um checkpoint é simplesmente esse número incremental, permitindo isolar trechos específicos de código para análise de alocações.

Estatísticas em Tempo Real

O kbmMW mantém contadores de memória alocada e número de alocações. Acesse esses dados através de propriedades estáticas:


lblContagemAlocVivas.Caption := IntToStr(TkbmMWDebugMemory.ContagemAlocacaoViva) +
  ' (' + IntToStr(TkbmMWDebugMemory.ContAlocVivaPorSeg) + '/seg)';
lblTamanhoAlocVivas.Caption := IntToStr(TkbmMWDebugMemory.TamanhoAlocacaoViva) +
  ' (' + IntToStr(TkbmMWDebugMemory.TamAlocVivaPorSeg) + '/seg)';
lblMaxContagem.Caption := IntToStr(TkbmMWDebugMemory.ContagemMaxAlocacao);
lblMaxTamanho.Caption := IntToStr(TkbmMWDebugMemory.TamanhoMaxAlocacao);
lblCapacidade.Caption := IntToStr(TkbmMWDebugMemory.CapacidadeContAlocAtual);

A propriedade ContagemAlocacaoViva representa alocações ativas, incluindo todos os tipos (Borland, Local, Global, Virtual, Heap). Observe que valores podem incluir alocações intermediárias (ex.: do FastMM), tornando-os comparativos, mas não absolutos.

Detectando Vazamentos no Encerramento

Vazamentos críticos ocorrem quando memória é alocada repetidamente sem liberação. O kbmMV permite verificar isso ao fechar o aplicativo, quando a maioria das alocações deveria ter sido desalocada.

Configure a detecção no início do aplicativo:


TkbmMWDebugMemory.DefinirDestinoRelatorio('c:\temp\vazamentos.txt');
TkbmMWDebugMemory.RelatarVazNoEncerramento := True;
TkbmMWDebugMemory.IniciarVerificacaoVazamentos;

Isso carrega informações de depuração e registra um checkpoint base. Alocações anteriores a este ponto (ex.: do RTL/VCL) são ignoradas. Para incluir todas as alocações desde o início, ajuste a linha de base:


TkbmMWDebugMemory.LinhaBase := 0;

Ao encerrar, o kbmMV gera um relatório de memória não liberada. Por padrão, exibe estatísticas na tela, como instâncias de classes e contagens. A precisão do rastreamento de pilha depende das informações de depuração compiladas. Para economizar recursos, desative a coleta de pilhas:


TkbmMWDebugMemory.ColetarPilhas := False;

Rastreamento em Trechos Específicos de Código

Para analisar alocações entre dois pontos, utilize checkpoints:


var
  cp1, cp2: TkbmMWDebugMemoryChaveAlocacao;
begin
  cp1 := TkbmMWDebugMemory.Checkpoint;
  // Código a ser analisado
  cp2 := TkbmMWDebugMemory.Checkpoint;
  GerarRelatorio(cp1, cp2);
end;

procedure GerarRelatorio(Chave1, Chave2: TkbmMWDebugMemoryChaveAlocacao);
var
  resultado: TkbmMWResultadoEscaneamentoMemoria;
begin
  resultado := TkbmMWResultadoEscaneamentoMemoria.Create;
  try
    TkbmMWDebugMemory.Escanear(resultado, Chave1, Chave2, [mwdmstObjeto]);
    resultado.Registrar(mwltDebug, mwllDetalhado, [mwsrpoSemPilha]);
  finally
    resultado.Free;
  end;
end;

O exemplo acima gera um log apenas de alocações de objetos, sem rastreamento de pilha.

Fonte original: https://components4developers.blog/2020/06/09/didyouknow-5-leakdetection/

Tags: kbmMW delphi FastMM gerenciamento de memória Depuração

Publicado em 7-28 02:18