Ao observar mais de perto a aplicação, podemos ver que existem três procedimentos de teste diferentes para simular problemas de memória:
Vazamentos de memória
procedureTMainForm.UniButton1Click(Sender: TObject);var P : PInt64;begin // Simular vazamento de memória: // Criamos uma instância de memória para Int64, mas não a liberamos (vazamento de memória)New(P); // A chamada abaixo encerrará o Standalone Server, então podemos ver a mensagem de erro de vazamento do FastMM imediatamente. // Isso é feito apenas para fins de demonstração. // Nunca chame "UniServerInstance.Terminate" no seu código de produção // Alternativamente, você pode comentar a linha abaixo e sair da aplicação manualmente. UniServerInstance.Terminate;end;
No evento acima tentamos simular um vazamento de memória criando um PInt64 instância. Como vazamentos de memória são reportados apenas na saída, encerramos a aplicação imediatamente para ver a caixa de mensagem de erro:
clip0361
Ao mesmo tempo, o vazamento de memória será registrado no arquivo de log do FastMM que será criado na mesma pasta.
Aqui estão os conteúdos parciais do arquivo de log:
Não apenas reporta a existência de um vazamento de memória, mas também registra a cadeia de métodos (rastreamento de pilha) que levou ao vazamento de memória:
Linha 46 no arquivo Main.pas — mostra a localização no código onde a memória foi alocada, mas não foi liberada:
clip0362
Corrupção de memória
O tipo mais importante de problemas de memória são as corrupções de memória, quando uma aplicação tenta alterar uma localização de memória que foi previamente liberada.
clip0363
Novamente podemos ver o mesmo erro no arquivo de log:
O log acima indica que o objeto de memória foi alocado na linha de código 61:
clip0364
O bloco foi previamente liberado pela thread 0x5164, e o rastreamento de pilha (endereços de retorno) no momento foi:
A memória alocada é descartada na linha 62.
Observe que o FastMM não é capaz de encontrar a linha exata do código onde a memória é alterada. O FastMM só pode detectar e relatar que uma localização de memória foi alterada depois de ter sido liberada e realocada.
Um bloco de memória foi vazado. O tamanho é: 12
Este bloco foi alocado pela thread 0x7580, e o rastreamento de pilha (endereços de retorno) no momento foi:
00406C36 [System.pas][System][GetMem][4189]
0088EC1A [Main.pas][Main][TMainForm.UniButton1Click$qqrp14System.TObject][46]
0078BA54 [uniGUIClasses.pas][uniGUIClasses][TUniControl.DoClick$qqrv][3694]
007EED2D [uniButton.pas][uniButton][TUniCustomButton.DoClick$qqrv][582]
007EE16C [uniButton.pas][uniButton][TUniCustomButton.ClickHandler$qqrp20Extpascal.TExtObject20System.UnicodeStringp23Uniguitypes.TUniStrings][358]
0075DB21 [uniGUIJSInterface.pas][uniGUIJSInterface][TUniJSHelper.HandleEvent$qqrx20System.UnicodeStringp20Extpascal.TExtObjectp23Uniguitypes.TUniStrings][1115]
0078DA9A [uniGUIClasses.pas][uniGUIClasses][TUniControl.HandleEventIntercept$qqrp20Extpascal.TExtObjectx20System.UnicodeString][4388]
0070EAF1 [ExtPascal.pas][ExtPascal][TExtThread.ObjectHandler$qqrp20Extpascal.TExtObjectx20System.UnicodeString][805]
007C0141 [uniGUIApplication.pas][uniGUIApplication][TUniGUISession.ObjectHandler$qqrp20Extpascal.TExtObjectx20System.UnicodeString][3648]
006FAA70 [ExtHTTPServer.pas][ExtHTTPServer][TIdExtSession.GetQuery$qqrx20System.UnicodeString][426]
0070EC6C [ExtPascal.pas][ExtPascal][TExtThread.HandleEvent$qqrv][828]
O bloco está atualmente sendo usado para um objectofclass: Unknown
O número da alocação é: 35353
procedure TMainForm.UniButton2Click(Sender: TObject);
var
P : PInt64;
begin
// Simular corrupção de memória:
// Criamos uma instância de memória para Int64 e a descartamos imediatamente
New(P);
Dispose(P);
// Agora tentamos acessar a localização de memória que já foi liberada.
// O FastMM irá detectar isso e exibirá uma mensagem de erro
P^ := 0;
end;
O FastMM detectou um erro durante uma operação GetMem. O FastMM detectou que um bloco foi modificado após ter sido liberado.
Offsets (e comprimentos) de bytes modificados: 0(3), 4(4)
O tamanho do bloco anterior era: 8
Este bloco foi previamente alocado pela thread 0x5164, e o rastreamento de pilha (endereços de retorno) no momento foi:
00406C36 [System.pas][System][GetMem][4189]
0088EC42 [Main.pas][Main][TMainForm.UniButton2Click$qqrp14System.TObject][61]
0078BA54 [uniGUIClasses.pas][uniGUIClasses][TUniControl.DoClick$qqrv][3694]
007EED2D [uniButton.pas][uniButton][TUniCustomButton.DoClick$qqrv][582]
007EE16C [uniButton.pas][uniButton][TUniCustomButton.ClickHandler$qqrp20Extpascal.TExtObject20System.UnicodeStringp23Uniguitypes.TUniStrings][358]
0075DB21 [uniGUIJSInterface.pas][uniGUIJSInterface][TUniJSHelper.HandleEvent$qqrx20System.UnicodeStringp20Extpascal.TExtObjectp23Uniguitypes.TUniStrings][1115]
0078DA9A [uniGUIClasses.pas][uniGUIClasses][TUniControl.HandleEventIntercept$qqrp20Extpascal.TExtObjectx20System.UnicodeString][4388]
0070EAF1 [ExtPascal.pas][ExtPascal][TExtThread.ObjectHandler$qqrp20Extpascal.TExtObjectx20System.UnicodeString][805]
007C0141 [uniGUIApplication.pas][uniGUIApplication][TUniGUISession.ObjectHandler$qqrp20Extpascal.TExtObjectx20System.UnicodeString][3648]
006FAA70 [ExtHTTPServer.pas][ExtHTTPServer][TIdExtSession.GetQuery$qqrx20System.UnicodeString][426]
0070EC6C [ExtPascal.pas][ExtPascal][TExtThread.HandleEvent$qqrv][828]