![]() |
Abort verursacht MemoryLeak ?
Guten Tag,
Ich habe hier ein MemoryLeakOnShutdown das verursacht wird wenn ich ein
Delphi-Quellcode:
and der kommentierten Stelle mache. Wenn ich das Abort auskommentiere verschwindet das MemoryLeak.
Abort;
Naja der Code Block ist sowieso abgearbeitet also könnte ich das Abort weglassen. Wenn aber durch eine Änderung noch mehr Code hinzukommt, komme ich um das Abort nicht herum da es sich um einen Fehler handelt, und die Routine abgebrochen werden soll. Zitat:
Delphi-Quellcode:
Ich habe im Debugger getestet ob das TryFinally sauber durchläuft und das tut es, auch wenn das Abort nicht auskommentiert ist. Also nach dem Abort läuft er ins finally.
procedure TMail.sendMassMail(_from, _subject: String; _delayInSeconds:Int64);
var i: Integer; msg: TIdMessage; begin try if not isFileEmpty(AppPath+mailListFilePath) then begin mailListText := TStringList.Create; mailListText.LoadFromFile(AppPath+mailListFilePath); for i := mailListText.Count-1 downto 0 do begin if Trim(mailListText[i]) = '' then begin mailListText.Delete(i); end else begin mailListText[i] := Trim(mailListText[i]); end; end; end else begin ShowMessage('MailListe ist leer. Abbruch!'); abort; end; if mailListText.Count < 1 then begin ShowMessage('Keine Empfänger in der MailListe. Abbruch!'); abort; end; if mailInit(_from,_subject) then begin if (mailListText.Count > 0) and (mailListText.Count < autoMailMaxCount) then begin msg := prepareMailMsg(_from,_subject); for i := 0 to mailListText.Count-1 do begin if (i mod autoMailPackageSendSize = 0) and (i <> 0) then begin Sleep(_delayInSeconds*1000); sendMail(mailListText[i],msg); end else begin sendMail(mailListText[i],msg); end; end; end else begin Showmessage('EMails können nicht an mehr als ' + IntToStr(autoMailMaxCount)+ ' Empfänger gesendet werden.'+#13#10+'Zu viele Empfänger in der Liste. Abbruch!' ); abort; // Dieses Abort verursacht das MemoryLeak, die anderen sind noch nicht getestet! end; end; finally FreeAndNil(msg); FreeAndNil(mailListText); FreeAndNil(attachmentsText); FreeAndNil(bodyText); end; end; Daher verstehe ich nicht warum ich durch dieses Abort ein MemoryLeak erhalte. Mfg Int3g3r |
AW: Abort verursacht MemoryLeak ?
.. wenn Du exit anstelle von abort verwenden würdest:
Zitat:
Klaus |
AW: Abort verursacht MemoryLeak ?
Jupp, in dieser Funktion wird das Finally immer ausgeführt.
Die Speicherlecks sind also eher außerhalb dieser Methode zu suchen. Und ja, Exit verlässt nur diese Methode, aber Abort bricht auch alle aufrufenden Methoden ab. Wenn es dann ein Speicherleck gibt, nach Abort oder einer anderen exception, dann hast du vermutlich irgendwo den Ressourcenschutzblock vergessen. Fehlerbehandlung mit ShowMessage, dafür sollte man auch gesteinigt werden. Versuche mal dieses sendMassMail innerhalb eines Try-Except zu benutzen. Ein Raise anstatt der Message würde die Behandlung erleichtern, denn so kann man außerhalb den Fehler nicht behandeln, loggen oder sonstwas. Außerdem wäre es nett, wenn du bitte erstmal die Compiler-Warnungen beachten würdest. Ich bin mir fast sicher, dass es für die Variable "msg" mindestens eine Warnung gibt. Zitat:
Mögliche Lösungen:
Delphi-Quellcode:
oder
msg := ...
try finally FreeAndNil(msg); end;
Delphi-Quellcode:
msg := nil;
try msg := ... finally FreeAndNil(msg); end; |
AW: Abort verursacht MemoryLeak ?
Hallo,
wo ist denn z.B. mailListText definiert? Warum ist das keine lokale Variable? Dann würde ich das so machen TMailListText = class(TStringList); und dann mailListText := TMailListText.Create; Dann siehst Du ja dann, ob es diese StringList ist, die "leaked". |
AW: Abort verursacht MemoryLeak ?
Zitat:
Darum verwende ich abort und nicht exit. Klar könnte ich jede Methode als Funktion schreiben und danach ein true/false zurückgeben. Dann kann ich aber nicht auf mehere Feher in der funktion reagieren.
Delphi-Quellcode:
// Dies ist imaginärer Code nur zum verdeutlichen warum ich Abort verwende:
procedure TForm1.Button1Click(Sender: TObject); begin setParameter; erstelleMail; sendMail; end; procedure TForm1.erstelleMail; begin //Mail Erstellen end; procedure TForm1.sendMail; begin //Mail Senden end; procedure TForm1.setParameter; begin //Parameter Setzen exit; end; Zitat:
Wie mache ich es besser ? Ein Bespiel / Tutorial wäre hilfreich. Zitat:
Einmal über das Problem schlafen und man findet das Problem in 10 Minuten ....:lol:
Delphi-Quellcode:
Danke für die Hilfe !
procedure TfrmMain.Button1Click(Sender: TObject);
var list: TStringList; begin list := TStringList.Create; list.Add('C:\...\bin\Win32\attach\Leaks.PNG'); list.Add('C:\...\bin\Win32\attach\recompile.PNG'); list.Add('C:\...\bin\Win32\attach\TelSpick.exe'); list.Add('C:\...\bin\Win32\attach\Unbenannt.PNG'); Mail := TMail.Create; Mail.sendMassMail('mail@gmx.ch','MassMail',10); //<- Abort list.Free; //<- Wird bei Abort nicht mehr Freigegeben .... end; Gruss Int3g3r |
AW: Abort verursacht MemoryLeak ?
Hallo,
Delphi-Quellcode:
Wenn es nicht anders geht:
list := TStringList.Create;
try list.Add('C:\...\bin\Win32\attach\Leaks.PNG'); list.Add('C:\...\bin\Win32\attach\recompile.PNG'); list.Add('C:\...\bin\Win32\attach\TelSpick.exe'); list.Add('C:\...\bin\Win32\attach\Unbenannt.PNG'); Mail := TMail.Create; Mail.sendMassMail('mail@gmx.ch','MassMail',10); //<- Abort finally list.Free; end; Außerdem arbeitest Du wieder mit quasi-globalen Variablen, hier Mail. Ich würde Mail z.B. im FormCreate erzeugen und in FormDestroy freigeben. |
AW: Abort verursacht MemoryLeak ?
Hier steht was zu
![]() Damit wird klar, warum das list.free nicht aufgerufen wird.
Delphi-Quellcode:
Abort ist letztlich auch nur 'ne Exception, deren Meldung "verschluckt" wird. Man kann sie aber im Exceptionhandling "abfangen" und damit auch in dem Fall ein "vernünftiges" Weiterlaufen des Programmes sicherstellen.
try
Funktion_die_im_Fehlerfalle_Abort_aufruft; except on e : EAbort do begin ShowMessage('Abort wurde aufgerufen.'); end; on e : Exception do begin MessageDLG(e.Message,mtError,[mbok],0); end; end; Mal ein annähernd sinnfreies Beispiel zum rumprobieren:
Delphi-Quellcode:
function Funktion_Bricht_Im_Fehlerfalle_Mit_Abort_ab(i : Integer) : Integer;
begin Result := 4812; if i < 0 then begin // Als Fehlerfall ist hier einfach mal i < 0 definiert. Abort; end else begin Result := Result div i; end; end; procedure TForm1.Button1Click(Sender: TObject); var list : TStringList; k : Integer; i : Integer; begin list := TStringList.Create; list.Add('irgendwas'); list.Add('nochwas'); i := 47; k := 12; try try // Wahlweise mit i = 0, i = -1 und i = 1 ausprobieren // und die Reihenfolge der Wertzuweisung zu i mal ändern. i := 1; k := Funktion_Bricht_Im_Fehlerfalle_Mit_Abort_ab(i); i := -1; k := Funktion_Bricht_Im_Fehlerfalle_Mit_Abort_ab(i); i := 0; k := Funktion_Bricht_Im_Fehlerfalle_Mit_Abort_ab(i); except on e : EAbort do begin MessageDlg(e.Message,mtError,[mbOk],0); end; on e : Exception do begin MessageDlg(e.Message,mtError,[mbOk],0); end; end; ShowMessage(Format('i = %d, k = %d',[i,k])); finally list.Free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:54 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz