3
votes

I've seen many mentions of bugs in Delphi 2009 generics, but never expected something so basic to fail in Update 3, no less. Calling IndexOf on a generic TList or TObjectList causes an access violation if the list contains 1 or more items:

type
  TTest = class( TObject );

procedure DoTest;
var
  list : TObjectList< TTest >;
  t : TTest;
begin
  list := TObjectList< TTest >.Create;
  try
    t := TTest.Create;
    list.IndexOf( t ); // No items in list, correct result -1
    list.Add( t );
    list.IndexOf( t ); // Access violation here
  finally
    list.Free;
  end;
end;

The exception is "EAccessViolation: Access violation at address 0048974C in module 'testbed.exe'. Read of address 00000000"

Compiling with debug DCUs leads to a problem in generics.collections.pas - the FComparer member is not assigned:

function TList<T>.IndexOf(const Value: T): Integer;
var
  i: Integer;
begin
  for i := 0 to Count - 1 do
    if FComparer.Compare(FItems[i], Value) = 0 then
      Exit(i);
  Result := -1;
end;

This of course makes the generic TList almost completely useless. Since Update 3 does not seem to have fixed this bug, do I have a recourse other than upgrading to XE?

2

2 Answers

8
votes

Have a look at this question. Why is TList.Remove() producing an EAccessViolation error?

In particular, try creating your TList like this

TList<TTest>.Create(TComparer<TTest>.Default);
6
votes

This is a bug in the default constructor of TObjectList<T>, and I thought it was fixed in update 3. If you're still seeing it, use a different constructor or just update to D2010 or XE, where it's definitely fixed. (And you'll really want to get off of D2009 if you want to work with generics anyway.)