Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

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

Inline + For-In + Exit + Packages = *peng*

  Alt 27. Apr 2015, 11:32
Delphi-Version: XE
Ich hatte jetzt mal einen total netten Fehler.

Der sorgte dafür, daß das Programm gleich total verreckte (Windows-Memdung > Programm reagiert nicht),
da das Programm sich mit Exceptions in einer Schleife selber lahmlegte.
  • Entweder Speicher überschrieben
  • und/oder bei den Rücksprungadressen, bzw. der Exceptionbehandlung (automatische Try-Finally) verhaspelt.

Vielleicht kennt ja bereits jemand dieses/soein Problem?
Ich muß mal sehn, wann ich Zeit finde das in einem kleinen Testprojekt nachzustellen.
Das sind die Sorte von Fehlern, wo man tagelang verzweifelt danach sucht.

Das Setting:
Delphi-Quellcode:
type
  TCacheDefinitionCollectionItem = class(TCollectionItem)
  public
    property LookupSource: TQueryClass read GetLookupSource;
  published
    property LookupName: string read FLookupName write SetLookupName;
  end;

  TCacheDefinitionCollection = class(TCollection)
  end;

  TCacheDefinition = class(TComponent)
  strict private
    FDefinition: TCacheDefinitionCollection;
  public
    function GetSource(LookupName: string): TQueryClass; inline;
  end;

function TCacheDefinition.GetSource(LookupName: string): TQueryClass;
var
  X: TCollectionItem;
  CI: TCacheDefinitionCollectionItem absolute X;
begin
  for {CI}X in FDefinition do
    if AnsiSameText(CI.LookupName, LookupName) then
      Exit(CI.LookupSource);
  Result := nil;
end;

function TSysDB.CacheLookup(LookupName, KeyFields: string; KeyValues: array of Variant; ResultField: string): Variant;
var
  Q: TPgQuery;
begin
  Q := CacheDefinition.GetSource(LookupName);
  Assert(Assigned(Q), 'TSysDB.CacheLookup(' + LookupName + ') nicht gefunden');
  Result := Q.Lookup(KeyFields, VarArrayOf(KeyValues), ResultField);
end;
und in einem anderen Runtimeepackage dann
Delphi-Quellcode:
procedure EinTFieldOnChangeEvent(Sender: TField);
begin
  if InEdit then // State in [dsEdit, dsIntert]
    AnderesField.Value := SysDB.CacheLookup('Laender', 'l_iso', Self.Value, 'lang_land');
end;
Der CacheLockup-Aufruf selber schien erstmal zu funktionieren, aber beim AnderesField.Value := knallte es dann (zu 99%)
und im Debugger konnte man dann sogar fleißig F9 drücken ... der Debugger blieb in der Zeile AnderesField.Value:= ) hängen und warf immer wieder eine Zugriffsverletzung bei ... (meisten eine ganz hoche Adresse, oberhalb der 2 GB des 32-Bit-Prozesses)

Inline hat über BPL-Grenzen ja bekanntlich eigentlich keine Wirkung und würde demnach ignoriert, aber dennoch führte es zum Totalversagen.
Ich weiß aber noch nicht, ob es auch in aktuellen Delphis so schön knallt.



absolute stört nicht ... kann man problemlos gegen manuelle Casts ersetzen.
Das zusammengesetzte Exit ist auch egal und kann man problemlos gegen Result:=...; exit; ersetzen.
Es scheint nur am For-In mit Exit in einer Inlinefunktion zu hängen, welches aus einem anderem Package aufgerufen wird.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat