Ratet mal, wofür es den Debugger gibt.
Wie Zacherl bereits erwähnte, gehört dein neuer Typ nicht zu den bekannten "Default"-Typen, für Welche in Delphi passende Comparer existieren,
also wird hier ganz einfach nur auf Type-Size gegangen und der Inhalt "Binär" verglichen.
Delphi-Quellcode:
class procedure TArray.Sort<T>(var Values: array of T);
begin
QuickSort<T>(Values, TComparer<T>.Default, Low(Values), High(Values));
end;
class function TComparer<T>.Default: IComparer<T>;
begin
Result := IComparer<T>(_LookupVtableInfo(giComparer, TypeInfo(T), SizeOf(T)));
end;
class procedure TArray.QuickSort<T>(var Values: array of T; const Comparer: IComparer<T>; L, R: Integer);
begin
...
while Comparer.Compare(Values[I], pivot) < 0 do
// Single
function Compare_R4(Inst: Pointer; const Left, Right: Single): Integer;
begin
if Left < Right then
// type Single
function Compare_U4(Inst: Pointer; const Left, Right: Cardinal): Integer;
begin
if Left < Right then
Du mußt dir also selber einen Comparer erstellen, für solche Typen.
TArray.Sort<TFloat>(Values, Comparer);
Die Zugriffsverletzung ist aber ein schwerwiegender Bug im QuickSort.
Ich bin echt erstaunt, daß es nicht öfters knallt.
Mit
Single
knallt es schon im Compare, wegen des NAN und weil die FPU so eingestellt ist.
>
Set8087CW SetExceptionMask
Bei
type Single
funktioniert der Vergleich, da "NAN" dort nicht behandelt wird, und es knallt im QuickSort.
Das erste
while Comparer.Compare(Values[I], pivot) < 0 do Inc(I);
findet kein Ende und trifft hier "zufällig" irgendwann auf nicht zugewiesenen Speicher.
Das Selbe wird man auch bei anderen Typen hinbekommen. Der BufferOverflow wird zum Glück abgefangen, da die Array-Grenzen im Anschluss geprüft werden und somit keine Schreibzugriffe außerhalb des Arrays auftreten.
Es knallt also immer wenn im Array und davor oder dahinter auch kein fremder reservierter Speicher mit einem passenden Wert gefunden wird.
Delphi-Quellcode:
class procedure TArray.QuickSort<T>(
var Values:
array of T;
const Comparer: IComparer<T>; L, R: Integer);
var
I, J: Integer;
pivot, temp: T;
begin
if (Length(Values) = 0)
or ((R - L) <= 0)
then
Exit;
repeat
I := L;
J := R;
pivot := Values[L + (R - L)
shr 1];
repeat
while Comparer.Compare(Values[I], pivot) < 0
do
Inc(I);
while Comparer.Compare(Values[J], pivot) > 0
do
Dec(J);
Sehr eigenartig ist auch, dass in diesem Generic die Bereichsprüfung nicht funktioniert.
>
{$RANGECHECKS ON}
bzw. in den Projektoptionen aktiviert