AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Fehlerbehandlung : Folgefehler ?

Ein Thema von himitsu · begonnen am 12. Feb 2016 · letzter Beitrag vom 12. Feb 2016
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#1

Fehlerbehandlung : Folgefehler ?

  Alt 12. Feb 2016, 14:13
Delphi-Version: XE
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.
  • Delphi-Referenz durchsuchenAbort, bzw. Delphi-Referenz durchsuchenEAbort
  • Und falls der Compiler den JMP von Delphi-Referenz durchsuchenExit oder Delphi-Referenz durchsuchenBreak in eine stille Exception optimiert. (z.B. beim Rausspringen aus einem Try-Except/Finally-Blocks)
  • ... i glob dat war's
$2B or not $2B

Geändert von himitsu (12. Feb 2016 um 14:20 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Fehlerbehandlung : Folgefehler ?

  Alt 12. Feb 2016, 14:29
Solche komischen Sachen muss man nur dann machen, wenn man etwas falsch implementiert hat, bzw. in so einem Ausnahmefall trotzdem noch etwas macht, bzw. etwas nicht korrekt zurücksetzt.
Delphi-Quellcode:
procedure TForm1.DoLoadSomething( const AFilename : string );
begin
  FSomething.Free;
  FSomething := TSomething.CreateFromFile( AFilename ); // da kann es knallen
end;
hinterlässt im Fehlerfall einen dangling Pointer.
Delphi-Quellcode:
procedure TForm1.DoLoadSomething( const AFilename : string );
var
  newSomething: TSomething;
begin
  newSomething := TSomething.CreateFromFile( AFilename ); // da kann es knallen
  try
    FSomething.Free; // da könnte es knallen
    FSomething := newSomething;
  except
    newSomething.Free;
    raise;
  end;
end;
Die Kernfrage ist immer: Wie hinterlasse ich das System in einem Ausnahmefall. Und das will gut überlegt sein.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (12. Feb 2016 um 14:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: Fehlerbehandlung : Folgefehler ?

  Alt 12. Feb 2016, 14:35
Nun ja, hier ist der Fehler doch der Ressourcenschutzblock ... lässt man den weg, ist alles OK.

Bzw. der Ressourcenschutzblock enthält selber Code, der zu einem Fehler führen kann.
Wenn vorher alles OK war, dann möchte ich den natürlich sehen, aber ansonsten halt ganz gern den ersten/eigentlichen/ursprünglichen Fehler.

Delphi-Quellcode:
try
  MachWas;
finally
  try
    RäumAuf;
  except
  end;
end;
So geht es auch, aber Schön ist was Anderes.





Pssst
Delphi-Quellcode:
procedure TForm1.DoLoadSomething( const AFilename : string );
begin
  FreeAndNil(FSomething); // hier kann es knallen, aber ist dennoch nil
  FSomething := TSomething.CreateFromFile( AFilename ); // da kann es auch knallen, aber egal
end;
Hier gibt es zimindestens keinen ungültigen Zeiger.
Bei dir wird immer dafür gesorgt, dass es eine TSomething-Instanz gibt.
$2B or not $2B

Geändert von himitsu (12. Feb 2016 um 14:43 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Fehlerbehandlung : Folgefehler ?

  Alt 12. Feb 2016, 14:43
Nun ja, hier ist der Fehler doch der Ressourcenschutzblock ... lässt man den weg, ist alles OK.

Bzw. der Ressourcenschutzblock enthält selber Code, der zu einem Fehler führen kann.
Wenn vorher alles OK was, dann möchte ich den natürlich sehen, aber ansonsten halt ganz gern den ersten/eigentlichen Fehler.
Das EndUpdate führt zu einem Fehler, weil vorher etwas falsch gemacht wurde.

Data.ReadComponent(Wrapper); macht etwas, obwohl es gar nichts machen kann (ist ja ein Lesefehler). Das ist der eigentliche Fehler.

Delphi-Quellcode:
procedure TForm1.DoLoadSomething( const AFilename : string );
begin
  FreeAndNil(FSomething); // hier kann es knallen, wenn uns jemand einen dangling pointer hinterlassen hat
  FSomething := TSomething.CreateFromFile( AFilename ); // da kann es knallen
end;
Delphi-Quellcode:
try
  MachWas;
finally
  try
    RäumAuf;
  except
  end;
end;
So geht es auch, aber Schön ist was Anderes.
Nein, in dem Fall geht das mit
Delphi-Quellcode:
try
  MachWas_AberNichtsKaputt;
except
  RäumAuf;
  raise;
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (12. Feb 2016 um 14:47 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Fehlerbehandlung : Folgefehler ?

  Alt 12. Feb 2016, 15:01
TReader liest halt bis dahin ein, wo es geknallt hatte, womit dann natürlich auch nur die Hälfte geladen wurde und es dann so "kaputt" bleibt.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz