Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

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

AW: Delphi-System-Funktion ersetzen

  Alt 3. Mär 2012, 14:08
Jupp.

Um Probleme einfacher finden zu können, vorallem da wo Fehlermeldungen überhaupt nichts helfen, da sie nichts oder nur Schwachsinn sagen.

Genauso werden einige Exception an die richtigen Adressen verlinkt.
Der Debugger hält nach Exceptions da, wo System.ExceptAddr hinzeigt.

Bei raise Exception.Create; hält der Compiler beim RAISE, wärend beim raise Exception.Create at ADDR; der Compiler bei ADDR stehenbleibt.
Ich laß es jetzt einfach dorthinzeigen, von wo diese Procedure aufgerufen wurde, was dann hoffentlich die eigentliche Fehlerverursachende Stelle sein sollte.
Denn leider schafft Delphi es oftmals nicht, vorallem kurz nach einer Exception, den Stacktrace aufzubauen, womit man dann nicht die Fehlerstelle sehen kann.


@jbg: Besser so?
Delphi-Quellcode:
procedure ExtendedIntfError(const Source: IInterface; const IID: TGUID; CallingAddress: Pointer);
const
  ObjCastGUID: TGUID = '{CEDF24DE-80A4-447D-8C75-EB871DC121FD}';
var
  S: string;
  GUID: TGUID;
  Obj: TObject;
  RTyp: TRttiType;
begin
  // Fehlermeldung und GUID des angeforderten Interfaces
  S := SIntfCastError + sLineBreak + GUIDToString(IID);
  // Interface-Bezeichnung suchen
  for RTyp in TRttiContext.Create.GetTypes do
    if RTyp is TRttiInterfaceType then begin
      GUID := TRttiInterfaceType(RTyp).GUID;
      if (RTyp is TRttiInterfaceType) and (PInt64(@GUID)^ = PInt64(@IID)^) and (PInt64(@GUID.D4)^ = PInt64(@IID.D4)^) then
        S := S + ' = ' + TRttiInterfaceType(RTyp).DeclaringUnitName + '.' + TRttiInterfaceType(RTyp).Name;
    end;
  // weitere Infos, wenn sich intern ein Delphi-Objekt versteckt
  if Source.QueryInterface(ObjCastGUID, Obj) <> 0 then begin
    // Bezeichnung der Klasse
    S := S + ' < ' + Obj.UnitName + '.' + Obj.ClassName;
    if Obj is TComponent then begin
      // Komponenten-Name
      if TComponent(Obj).Name <> 'then
        S := S + '-' + TComponent(Obj).Name;
      // worauf sich diese Komponente befindet
      if Obj is TWinControl then
        while Assigned(TWinControl(Obj).Parent) do begin
          Obj := TWinControl(Obj).Parent;
          if (Obj is TForm) or (Obj is TFrame) then begin
            S := S + '@' + Obj.UnitName + '.' + Obj.ClassName;
            if TComponent(Obj).Name <> 'then
              S := S + '-' + TComponent(Obj).Name;
          end;
        end;
    end;
  end;
  raise EIntfCastError.Create(S) at CallingAddress;
end;

procedure ExtendedIntfCast(var Dest: IInterface; const Source: IInterface; const IID: TGUID);
var
  Intf: IInterface;
begin
  if Source = nil then
    Dest := nil
  else if Source.QueryInterface(IID, Intf) = 0 then
    Dest := Intf
  else
    ExtendedIntfError(Source, IID, ReturnAddr);
end;
Das GUIDToString(IID) und // Interface-Bezeichnung suchen könnte ich zwar auslagern und nur bei Anzeige/Anfrage konvertieren und suchen, indem einfach nur die GUID (IID) in der Exception bespeichert würde, aber leider ist irgendwer auf die saublöde Idee gekommen Exception.Message nicht mit einem virtuellen Getter zu versehn, genauso wie Exception.StackTrace auch nicht virtual ist, so daß man wohl nicht umherkommt alles sofort zu erstellen und nicht erst, wenn wirlich benötigt.
$2B or not $2B
  Mit Zitat antworten Zitat