5

We have some old classes using Contnrs.TObjectList, and in some cases custom compare-functions are used to sort these lists, using something like this:

procedure TMyClass.SortItems;

  function CompareFunction(Item1, Item2: Pointer): Integer;
  begin
    Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
  end;

begin
  Sort(@CompareFunction);
end;

This code has worked without issues when compiled for Win32, but when we compile it for Win64, we have found that the sorting doesn't work anymore.

I have fixed some of them by using Generics.Collections.TObjectList<T> instead, and modifying the CompareFunction and how it is called. So my guess is that it has to do with the way the CompareFunction is called, by prefixing it with the @ operator, which as I understand, refers to the address of the function.

Why does the code above doesn't work on Win64, and what would be the proper way to fix it?

alondono
  • 2,496
  • 2
  • 28
  • 34

1 Answers1

7

TObjectList.Sort() expects a standalone function for its callback.

An inner function shares the stack frame of its parent function (so it can access the parent's local variables and parameters). So you can't use an inner function as the callback. You got away with it in 32bit, due to a fluke in how functions work in 32bit. But this won't work anymore in 64bit.

You need to move CompareFunction() out on its own, eg:

function CompareFunction(Item1, Item2: Pointer): Integer;
begin
  Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
end; 

procedure TMyClass.SortItems;
begin
  Sort(@CompareFunction);
end;

This will work in both 32bit and 64bit.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Oh, that was easy. Thanks. I've tried it, and I even noticed that when using the standalone function I can omit the `@` operator, using simply `Sort(CompareFunction)` – alondono Nov 23 '17 at 05:17
  • @alondono, good you noticed that! I recommend getting into the habit of never using `@` for function pointers except when you're forced to **and** know what you do. :-) – Uli Gerhardt Nov 23 '17 at 06:29