Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi AV in Callback-Funktion (https://www.delphipraxis.net/110346-av-callback-funktion.html)

Dani 16. Mär 2008 21:15


AV in Callback-Funktion
 
Liste der Anhänge anzeigen (Anzahl: 1)
Guten Abend :hi:

Ich steh grad total auf dem Schlauch. In einer Klassenmethode wird eine Callback-Funktion aufgerufen, aber die Parameter werden anscheinend nicht richtig gesetzt, denn ein Zugriff auf die Parameter löst eine AV aus. Die verletzende Adresse ist niedrig ($00000014, $00000020, $0000000F, ...).

Die Callback-Funktion ist TSortRelation:
Delphi-Quellcode:
type
  TSortRelation = function(A, B: TObject): Integer of object;
Hier der Aufruf:
Delphi-Quellcode:
class procedure THeapsorter.Sort(List: TObjectList; Relation: TSortRelation);
  procedure BubbleUp(N: Integer);
  var
    I: Integer;
    X: TObject;
  begin
    (* Fuege List[N-1] in den Heap List[0],...,List[N-1] ein *)
    I := N;
    X := List[N - 1];
    // AV beim Aufruf von Relation() mit korrekten Indizes, z.B. 7 und 4
    // bei einer Liste mit 10 Elementen.
    while (I >= 2) and (Relation(List[I div 2 - 1], X) < 0) do begin
      List[I - 1] := List[I div 2 - 1];
      I := I div 2;
    end;
    List[I - 1] := X;
  end;

  {...}

begin
  {...}
end;
Und eine Implementierung von TSortRelation:
Delphi-Quellcode:
type
  TWrappedString = class(TObject)
  private
    FStr: WideString;
  public
    property Str: WideString read FStr write FStr;
    constructor Create(Str: WideString); reintroduce;
  end

function TForm1.StrCompareAsc(A, B: TObject): Integer;
var
  G1, G2: TWrappedString;
  S1, S2: WideString;
begin
  Inc(CmpCount);
  if (CmpCount mod 1000000 = 0) then begin
    Caption := IntToStr(CmpCount);
    Application.ProcessMessages;
  end;

  if (A = nil) and (B = nil) then Result := 0
  else if (A = nil) then Result := -1
  else if (B = nil) then Result := 1
  else begin
    // AV in nächster Zeile bei "as"
    G1 := A as TWrappedString;
    G2 := B as TWrappedString;
    S1 := G1.Str;
    S2 := G2.Str;
    Result := WideCompareStr(S1, S2);
  end;
end;
Wenn ich aus TSortRelation eine "normale" Funktion anstelle einer Klassenmethode mache (also "of object" weglasse und StrCompareAsc entsprechend ändere), bleibt die AV trotzdem. Was mache ich falsch? :gruebel:

Edit: huch, meine Delphi-Tags haben sich ins [pre]s verwandelt!?

Muetze1 16. Mär 2008 21:28

Re: AV in Callback-Funktion
 
Gebe beim anlegen der TObjectList im Create ein false mit anstatt einem true. Du hast jetzt das Problem, dass du dir selber die Instanzen zerschiesst. Grund dafür ist die Zuweisung von Listenelementen. Wenn du folgendes im Code machst:

Delphi-Quellcode:
List[I - 1] := List[J - 1];
Dann wird das Element links (i-1) freigegeben bevor das neue Element zugewiesen wird. Damit zerschiesst du dir mit jeder Zuweisung die Liste, da du nicht mehr weisst ob eine Instanz noch gültig ist oder nicht. Damit ist dann jeder Zugriff auf die Typeninformationen der Klasse (Grund des Absturzes durch den AS Operator) genauso wie der Zugriff auf den String tödlich.

Dani 16. Mär 2008 22:44

Re: AV in Callback-Funktion
 
Ah, klar...müsste eigentlich reichen, OwnsObjects temporär auf false zu stellen.... Danke!


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:38 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