2016-09-19 2 views
6

Ich habe eine Konsolenanwendung erstellt und ReportMemoryLeaksOnShutdown: = True festgelegt.Melden von Speicherverlusten beim Herunterfahren mit einer Konsolenanwendung

Ich habe eine TStringList erstellt, aber nicht freigegeben.

Wenn das Programm beendet wird, sehe ich den Speicherverlust für eine kurze Sekunde, aber dann schließt die Konsole.

Ich habe versucht, ein ReadLn; bis zum Ende, aber es zeigt nur ein leeres Konsolenfenster, wenn ich das mache, was Sinn macht.

Ich muss einen Weg finden, die Ausführung nach dem Speicherleckbericht, aber vor dem vollständigen Programmabbruch anzuhalten.

Ich benutze Delphi 10 Seattle.

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

Führen Sie das Programm in einem zuvor geöffneten Befehlsfenster aus, nicht in der IDE. –

+1

Du könntest *** meine 'AutoConsole'-Einheit ausprobieren, siehe hier: http://rvelthuis.blogspot.de/2016/07/new-vethuisautoconsole-unit.html. Fügen Sie es einfach zu Ihrem Konsolenprogramm hinzu. –

+0

Fügen Sie einen Haltepunkt auf "system.end" hinzu. –

Antwort

6

Am einfachsten ist es, die Anwendung einfach in einem zuvor geöffneten Befehlsfenster auszuführen.

Wenn Sie darauf bestehen, den Speicherverlust Bericht zu sehen, während in der IDE ausgeführt wird, gehen Sie wie folgt vor:

  • Suchen Sie die Showmessage Verfahren in GetMem.inc (Linie 4856 in Delphi 10 Seattle)
  • Platz ein Haltepunkt auf der end; dieses Verfahrens.

Alternativ kann, wie Sertac Akyuz kommentierte, legte einen Haltepunkt auf der end. der system Einheit.

Sie können den Speicherleckbericht auch in eine Datei umleiten. Laden Sie die Vollversion von FastMM von

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

oder besser, dank Ariochs ‚Die, von hier:

https://github.com/pleriche/FastMM4

und legen Sie die benötigten Optionen in FastMM4Options.inc

+2

Dies ist ein bisschen alt URL, neu ist github.com/pleriche/FastMM4 –

+0

er kann es auch um Windows Debug Strings Einrichtung umleiten, aber ich glaube nicht, dass das Problem seiner Frage ist –

7

Das heißt ein Bug in den letzten Delphi-Versionen. Ich habe es gerade in diesem kürzlich kostenlosen Delphi 10.1 Starter überprüft und es verhält sich wie beschrieben - aber da es keine RTL-Quellen bietet, kann ich den genauen Grund nicht überprüfen.

In Delphi XE2 verhält es sich wie erwartet: erstellt den task-modalen Dialog und wartet darauf, dass Sie reagieren, wie von Sertak beschrieben.

In Delphi 10.1 wird das Leck tatsächlich an das Konsolenfenster gemeldet, aber das Programm wird nicht angehalten, um auf die Aufmerksamkeit des Benutzers zu warten. Dies ist sowohl aus diesem Grund als auch für die mögliche Verwendung von Konsolenprogrammen beim Scripting eine schlechte Lösung (CMD- oder PS-Skripte würden diese Nachricht nicht "verstehen" und könnten sie mit der legitimen Ausgabe und der Ausführung weiterer Stufenprogramme verwechseln.

Ich denke, Sie müssen den Regressions-Fehlerbericht über Delphi 10.0 öffnen - aber ich denke nicht, dass sie es bis zur Version 10.2 beheben würden.

Ich habe auch Ihre Anwendung von Delphi-Gabelspeicher-Manager auf die ursprüngliche umgeschaltet, und dann wurde das fehlerhafte Verhalten zurückgesetzt: Das Programm zeigte das Meldungsfeld und wartete, bis ich es vor dem Beenden in die IDE entlassen.

Momentan empfehle ich Ihnen, den erwähnten originalen Speichermanager anstelle von Delphi Fork zu verwenden.

program Project1; 

{$APPTYPE CONSOLE} 

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

Der ursprüngliche Speicher-Manager befindet sich auf http://github.com/pleriche/FastMM4 Sie Git-Client in Ihrem Delphi oder ein eigenständiges selbst eine Beurteilung aktualisiert verwenden können, zu halten, oder Sie können den Code einmal herunterladen und stoppen Sie die Aktualisierung, auf.

Die entsprechenden Zitate seines Codes sind:

{$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; 

und

{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; 

Dieser Code hängt von auf Desktop-Windows ausgeführt wird, so vielleicht Embarcadero versucht, zu "reparieren" es zu machen überqueren -Plattform. Aber die Art, wie sie es getan haben, brach es auf Windows-Konsole ....

Denken Sie auch über das Hinzufügen anderer Formen der Protokollierung - in die Datei und/oder in die Windows-Debug-Strings. Sie würden nicht so auffällig sein wie das modale Fenster, aber würden Ihnen zumindest helfen, die Informationen zu speichern, wenn Sie wissen würden, wo Sie danach suchen müssen.

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

Fehler sind wahrscheinlich fällig versuchen, Speicher für readln zu erwerben, nachdem der Manager abgeschlossen ist. Unter Windows kann durch eine Messagebox ersetzt werden. –

+0

@SertacAkyuz Win32 messagebox hat ein Problem: Sie können einen Text nicht aus der Zwischenablage kopieren. WENN das wirklich benötigt wird - Ich würde einen Stub-Manager neu installieren, alle Delphi-Aufrufe an Win32 LocalAlloc und Freunde weiterleiten –

+0

@Arioch - Es ist anstelle der readln, um die Ausführung zu stoppen - es gibt nichts zu kopieren. Zweitens irren Sie sich, drücken Sie Strg + C auf einem Standard-API-Meldungsfeld und die Beschriftung und der Text und der Text der Schaltflächen werden in die Zwischenablage kopiert. –

Verwandte Themen