2016-09-19 46 views
6

Bir konsol uygulaması oluşturdum ve ReportMemoryLeaksOnShutdown: = True değerini ayarladım.Konsol uygulamasıyla kapatma sırasında bellek sızıntılarını bildirme

Bir TStringList oluşturdum ama serbest bırakmadım.

Program yürütmeyi bitirdiğinde, kısa bir saniye için bellek sızıntısı görüyorum ancak konsol kapanıyor.

Bir ReadLn eklemeyi denedim; sonuna kadar, ancak bunu yaptığımda sadece boş bir konsol penceresi gösterir, bu da mantıklı.

Bellek sızıntısı raporundan sonra ancak programın kapatılmasından önce yürütmeyi duraklatmanın bir yolunu bulmalıyım.

Delphi 10 Seattle kullanıyorum.

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    System.Classes, 
    System.SysUtils; 

var 
    s : TStringList; 

begin 
    try 
    ReportMemoryLeaksOnShutdown := True; 
    s := TStringList.Create; 

    //ReadLn doesn't work here, which makes sense. 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    //I need to be able to pause the program somewhere after the end statement here. 
end. 
+6

Programı önceden açılmış bir komut penceresinde, IDE'de değil, çalıştırın. –

+1

*** "AutoConsole" birimimi *** deneyebilirsiniz, buraya bakın: http://rvelthuis.blogspot.de/2016/07/new-velthuisautoconsole-unit.html. Sadece konsol programınıza ekleyin. –

+0

"system.end" üzerinde bir kesme noktası ekleyin. –

cevap

6

En kolay, uygulamayı daha önce açılmış bir komut penceresinde çalıştırmaktır.

ıde çalışırken, bellek sızıntısı raporu gördükten ısrar yaparsanız aşağıdaki gibi:

  • Yeri a (Delphi 10 Seattle hat 4856) GetMem.inc içinde ShowMessage prosedürünü bulun Bu yordamın end; üzerinde kesme noktası. Sertaç Akyüz tavsiye edildiği gibi

Alternatif olarak, system biriminin end. bir kesme noktası koydu.

Bellek sızıntısı raporunu bir dosyaya da yönlendirebilirsiniz.

https://github.com/pleriche/FastMM4

ve olduğu FastMM4Options.inc

+2

Bu biraz eski bir URL, yeni bir tane github.com/pleris/FastMM4 –

+0

o da Windows Debug Strings tesisine yeniden yönlendirebilir, ama ben onun sorununun sorunu olduğunu düşünmüyorum –

7

gerekli seçenekleri ayarlayın: buradan,

https://sourceforge.net/projects/fastmm/

veya daha iyi, Aryok 'The sayesinde gelen FastMM tam sürümünü indirin son Delphi sürümlerinde bir hata. Ben sadece bu yeni ücretsiz Delphi 10.1 Starter'da kontrol ettim ve açıkladığınız gibi davranıyor - ama hiçbir RTL kaynağı sağlamadığı için tam sebebi kontrol edemiyorum.

Delphi XE2'de beklendiği gibi davranır: Görev-modal iletişim kutusunu oluşturur ve aynen Sertak tarafından açıklandığı gibi tepki vermenizi bekler.

Delphi 10.1'de sızıntı gerçekten konsol penceresine bildirilir, ancak kullanıcı dikkatini çekmek için program durdurulmaz. Bu, hem bu nedenle hem de komut programlarındaki konsol programlarının olası kullanımı için zayıf bir çözümdür (CMD veya PS komut dosyaları bu mesajı "anlayamayacak" ve bunun yanlış çıktısı ile karıştırılmasına ve ileri aşama programlarının başarısız olmasına neden olabilir.

Bence, Delphi 10.0 üzerinden regresyon tipi hata raporunu açmalısın - ama 10.2 sürümüne kadar düzelteceklerini sanmıyorum.

Ayrıca uygulamanızı Delphi-forked bellek yöneticisinden özgün olana değiştirdim ve sonra hatalı davranış geri döndürüldü: program ileti kutusunu görüntüledi ve IDE'ye çıkmadan önce onu reddetene kadar bekledim.

Şu anda Delphi çatalı yerine belirtilen orijinal bellek yöneticisini kullanmanızı öneririm. http://github.com/pleriche/FastMM4 Sen Delphi Git istemcisi kullanabilir veya bağımsız bir kendin güncel tutmak veya tek seferde kodu indirip size kalmış, güncellenmesi durdurabilir de

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    FastMM4, 
    System.Classes, 
    System.SysUtils; 
... 

orijinal bellek yöneticisi bulunur.

onun kod alakalı tırnak gibidir:

{$ifdef LogErrorsToFile} 
    {Set the message footer} 
     LMsgPtr := AppendStringToBuffer(LeakMessageFooter, LMsgPtr, Length(LeakMessageFooter)); 
     {Append the message to the memory errors file} 
     AppendEventLog(@LLeakMessage[0], UIntPtr(LMsgPtr) - UIntPtr(@LLeakMessage[1])); 
    {$else} 
     {Set the message footer} 
     AppendStringToBuffer(LeakMessageFooter, LMsgPtr, Length(LeakMessageFooter)); 
    {$endif} 
    {$ifdef UseOutputDebugString} 
     OutputDebugStringA(LLeakMessage); 
    {$endif} 
    {$ifndef NoMessageBoxes} 
     {Show the message} 
     AppendStringToModuleName(LeakMessageTitle, LMessageTitleBuffer); 
     ShowMessageBox(LLeakMessage, LMessageTitleBuffer); 
    {$endif} 
    end; 
    end; 
{$endif} 
end; 

ve

{Shows a message box if the program is not showing one already.} 
procedure ShowMessageBox(AText, ACaption: PAnsiChar); 
begin 
    if (not ShowingMessageBox) and (not SuppressMessageBoxes) then 
    begin 
    ShowingMessageBox := True; 
    MessageBoxA(0, AText, ACaption, 
     MB_OK or MB_ICONERROR or MB_TASKMODAL or MB_DEFAULT_DESKTOP_ONLY); 
    ShowingMessageBox := False; 
    end; 
end; 

Bu kod masaüstü Windows üzerinde yürütülüyor bağlıdır, bu yüzden belki Embarcadero buna çapraz yapmak için "düzeltmek" için çalıştı -platform. Ancak bunu yaptıklarını Windows konsolunda bozdular.

Ayrıca, diğer günlüğe kaydetme formlarını eklemeyi de düşünebilirsiniz - dosyaya ve/veya Windows Hata Ayıklama Dizeleri içine. Modal penceresi kadar dikkat çekici olmayacaklardı, ama en azından bilgiyi nereye saklayacaklarını bilseydiniz, bilgiyi saklamanıza yardımcı olacaklardı.

4
var 
    SaveExitProcessProc: procedure; 
    s: TStringList; 

procedure MyExitProcessProc; 
begin 
    ExitProcessProc := SaveExitProcessProc; 
    readln; 
end; 

begin 
    SaveExitProcessProc := ExitProcessProc; 
    ExitProcessProc := MyExitProcessProc; 
    ReportMemoryLeaksOnShutdown := True; 
    s := TStringList.Create; 
end. 
+1

Hatalar büyük olasılıkla Yönetici sonlandıktan sonra readln için hafıza almaya çalışıyor. Pencerelerde bir mesaj kutusu ile değiştirilebilir. –

+0

@SertacAkyuz Win32 messagebox bir sorunla karşılaştı: bir metni panoya kopyalayamıyorsunuz. Aslında bu gerekli - Eğer bir Delphi çağrıları yeniden yüklemek için Win32 LocalAlloc ve arkadaşları –

+0

@Arioch yönlendirme bir saplama yöneticisi yeniden - Ben, yürütme durdurmak için readln yerine - kopyalanacak bir şey yok. İkincisi yanılıyorsunuz, standart bir api mesaj kutusu üzerinde ctrl + c tuşlarına basın, altyazı ve metin ile düğmelerin metni panoya kopyalanacaktır. –