Moin,
sowas ist mir schon mehrmals untergekommen, daß ein Folgefehler die eigentliche Fehlermeldung geschrottet hat.
Jetzt hab ich das nochmal und konnte diesmal den Verursacher rausfinden.
Sollte man nun Folgefehler beachten, oder nicht?
Eigentlich muß man ja nur den ersten Fehler behandeln und der Zweite ist auch weg, bzw. man müsste den ersten Fehler erstmal kennen, was schwerer wird, wenn der sich in einer größeren Funktion versteckt und man durch den Folgefehler nicht das Wo erkennen kann.
[blabla]
GridFilter werden gespeichert, später wieder geladen und können zwischen den Installationen synchronisiert werden.
Die Spalten im Grid werden aus dem DataSet generiert und die
Query kann über die Synchro angepasst werden.
Der Filter greift nun auf eine Spalte zu, welche es inzwischen nicht mehr gibt.
Beim Laden des Filters knallt es nun in ReadComponent (Column fehlt und Property kann nicht geladen werden)
und beim Filter.EndUpdate oder Active=True wird auch nochmal auf diese (nichtexstierende=nil) Column zugegriffen und es knallt nochmal.
[/blabla]
Delphi-Quellcode:
//procedure TcxFilterCriteria.LoadFromStream(Data);
Filter.EndUpdate
GridView.DataController.Filter.BeginUpdate;
try
Wrapper := TFilterWrapper.Create(nil);
try
Wrapper.Filter := GridView.DataController.Filter;
Data.ReadComponent(Wrapper); ///// Stream-Lesefehler /////
finally
Wrapper.Free;
end;
finally
GridView.DataController.Filter.EndUpdate; ///// Zugriffsverletzung /////
end;
Der Kunde und auch wir sehen also erstmal nur das "Zugriffsverletzung"
Die aktuelle Lösung besteht nun also darin den Folgefehler zu unterdrücken.
Delphi-Quellcode:
//GridView.DataController.Filter.LoadFromStream(Data);
{$REGION 'TcxFilterCriteria.LoadFromStream'}
// Am Ende von TStream.ReadComponent wird aus einem "Fehler beim Lesen von _1.Filter.Criteria: Stream-Lesefehler"
// in TcxFilterCriteria.EndUpdate ein nichtssagendes "Zugriffsverletzung bei Adresse 0".
Filter.EndUpdate
GridView.DataController.Filter.BeginUpdate;
try
Wrapper := TFilterWrapper.Create(nil);
try
Wrapper.Filter := GridView.DataController.Filter;
Data.ReadComponent(Wrapper);
finally
Wrapper.Free;
end;
finally
//GridView.DataController.Filter.EndUpdate;
if System.ExceptObject = nil then
GridView.DataController.Filter.EndUpdate
else
try GridView.DataController.Filter.EndUpdate; except end; // tritt hier ein Folgefehler auf, dann würde die originale Fehlermeldung geschrottet.
end;
{$ENDREGION}
GridView.DataController.Filter.Active := True;
Delphi-Quellcode:
procedure TcxFilterCriteria.LoadFromStream(AStream: TStream);
var
AWrapper: TFilterWrapper;
begin
BeginUpdate;
try
AWrapper := TFilterWrapper.Create(nil);
try
AWrapper.Filter := Self;
AStream.ReadComponent(AWrapper);
finally
AWrapper.Free;
end;
finally
if System.ExceptObject = nil then
EndUpdate
else
try EndUpdate; except end; // tritt hier ein Folgefehler auf, dann würde die originale Fehlermeldung geschrottet.
end;
end;
Oder vielleicht besser gleich auch für alle anderen Codestellen?
Delphi-Quellcode:
procedure TcxFilterCriteria.EndUpdate;
begin
Dec(FLockCount);
if System.ExceptObject =
nil then
CheckChanges
else
try CheckChanges;
except end;
// tritt hier ein Folgefehler auf, dann würde die originale Fehlermeldung geschrottet.
end;
Als Pattern also irgendwie so?
Delphi-Quellcode:
procedure TMyClass.EndUpdate;
var
HasError: Boolean;
begin
HasError := System.ExceptObject <> nil;
try
....
except
if not HasError then
raise;
end;
end;
////////////////////////////////////////////////////////////////
procedure TMyClass.EndUpdate;
begin
try
....
except
if not Assigned(PRaiseFrame(RaiseListPtr)^.NextRaise) then // Kürzer, aber funktioniert nicht bei PC_MAPPED_EXCEPTIONS
raise;
end;
end;
Im Grunde müsste man jetzt noch bestimmte Sonderfälle beachten, wenn man eine allgemeine Lösung sucht, was aber bei uns erstmal nicht vorkommt.
- Abort, bzw. EAbort
- Und falls der Compiler den JMP von Exit oder Break in eine stille Exception optimiert. (z.B. beim Rausspringen aus einem Try-Except/Finally-Blocks)
- ... i glob dat war's