Guten Abend
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?
Edit: huch, meine Delphi-Tags haben sich ins [pre]s verwandelt!?
Dani H.
At Least I Can Say I Tried