![]() |
EAccessViolation mit StringListe
Hallo.
Ich habe eine Situation die ich leider nicht nachvollziehen kann. Es geht um eine Access Vialotion in eine Quelcode Zeile die nur ab und zu kommt. Ich konnte den Fehler noch nicht nachstellen. Nur Nachträglich im LogFile auslesen. Die abgekürzte fassung der Funktion:
Delphi-Quellcode:
Die Fehlermeldung:
Function TDMAng.CheckRV(RD:TStringList;var errlist:TStringList):boolean;
begin result:=true; if not assigned(errlist) then errlist:=TStringList.Create; errlist.Clear; //viele Prüfungen ... if bPasstNicht then errlist.Add('"215","'+'Hinweis: '+'Passt nicht!') //viele Prüfungen... result:= errlist.count=0; end; madExcept version : 4.0.12 callstack crc : $00000000, $48d61ed6, $48d61ed6 exception number : 1 exception class : EAccessViolation exception message : Zugriffsverletzung bei Adresse 00000000. Lesen von Adresse 00000000. Dei Fehlerzeile ist mal "errlist.Clear;" oder "result:= errlist.count=0;". Ich vermute das die Prüfung "if not assigned(errlist)" manchmal nicht greift. Kann man die Funktion irgendwie optimieren? |
AW: EAccessViolation mit StringListe
Der gezeigte Code-Teil an sich kann keinerlei Exceptions erzeugen, mit Ausnahme einer Einzigen, welche sich EOutOfMemory nennt.
Zitat:
Pssst, ich glaub in deinem errlist.Add fehlt ein ", aber für den Fehler hier ist es egal. :stupid: Und bezüglich
Delphi-Quellcode:
sollte der Compiler auch was sagen, falls sich nicht irgendwo ein Exit; versteckt, aber auch erstmal egal.
result:=true;
|
AW: EAccessViolation mit StringListe
Wenn errlist manchmal einen ungültigen Zeiger enthält, liegt das vermutlich daran, dass diese übergebene Liste irgendwo mit Free freigegeben, die Variable aber weiter verwendet wird.
Wenn du dort stattdessen FreeAndNil benutzt, funktioniert auch die Prüfung mit Assigned. Allerdings stimmt architektonisch dort etwas nicht, wenn manchmal, aber nicht immer, Instanzen in einer solchen Routine erzeugt werden. Für Erstellung und Freigabe muss immer jemand konkret zuständig sein, am besten in der gleichen Ebene (sprich z.B. nicht in einer Klasse die Erzeugung und in einer anderen die Freigabe). |
AW: EAccessViolation mit StringListe
Delphi-Quellcode:
Erstmal das "var" beim Prozedurkopf für errlist rausnehmen. Das könnte das Problem schon beheben.
//Function TDMAng.CheckRV(RD:TStringList;var errlist:TStringList):boolean;
Function TDMAng.CheckRV(RD:TStringList;errlist:TStringList):boolean; begin result:=true; if not assigned(errlist) then errlist:=TStringList.Create; errlist.Clear; //viele Prüfungen ... if bPasstNicht then errlist.Add('"215","'+'Hinweis: '+'Passt nicht!') //viele Prüfungen... result:= errlist.count=0; end; Ansonsten den Debugger nutzen und prüfen, wie die Inhalte sind und wo diese sich ändern und damit eine AV auslösen. EDIT: Den Unsinn mit dem "var" bitte ignorieren. |
AW: EAccessViolation mit StringListe
Zitat:
Nein, wenn der Zeiger ungültig ist, dann bleibt er das auch, egal ob mit oder ohne Var, da sich innerhalb dieser Funktion rein garnichts ändert. Und was jaenicke meint: * entweder jemand in der gleichen Klasse kümmert sich um die Freigabe, oder garnichts erstellen * oder wenn errlist Assigned ist, dann die Fehler loggen, bzw. ansonsten nur der Boolean-Result |
AW: EAccessViolation mit StringListe
Zitat:
|
AW: EAccessViolation mit StringListe
Zitat:
Ich würde die Liste nicht als Var-Parameter übergeben. Dadurch ist nicht mehr ersichtlich wer die Hoheit über die Liste hat, und wer sie freizugeben hat. Sauberer wäre aus meiner Sicht, du baust eine lokale Liste auf, gibst nur den String zurück, und fügst den String dann in die eigentliche Liste ein. Also so in etwa:
Delphi-Quellcode:
function CheckRV(RD:TStringList; out ErrorText: String): Boolean;
var ErrorList: TStringList; begin ErrorList := TStringList.Create; try result:=true; //viele Prüfungen ... if bPasstNicht then ErrorList.Add('"215","'+'Hinweis: '+'Passt nicht!') //viele Prüfungen... result:= ErrorList.count=0; ErrorText := ErrorList.Text; finally FreeAndNil(ErrorList); end end; procedure foo; var lstError: TStringList; ErrorText: String; begin lstError := TStringList.Create; try if not CheckRV(dummy, ErrorText) then lstError.Text := lstError.Text + ErrorText; finally FreeAndNil(lstError); end end; |
AW: EAccessViolation mit StringListe
Hallo,
Zitat:
Wer die Liste erzeugt, muss sie auch wieder freigeben. Falls der Aufwand zu gross ist, dann sollte die Liste mit FreeAndNil freigegeben werden. Zur Not hilft auch ein Singleton-Pattern, um sicherzustellen, dass die StringListe wirklich nur einmal erzeugt wird. |
AW: EAccessViolation mit StringListe
Danke an alle.
Ich werde den Vorschlag von SebastianZ ümsetzen. Ich denke auch das ein String als Var-Parameter unproblematischer ist. Vielen Dank. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:37 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 by Thomas Breitkreuz