TDeque access violation on destroy when empty and contains a managed type

Summary

System Information

  • Operating system: Windows 10
  • Processor architecture: x86-64
  • Compiler version: 3.2.2
  • Device: Computer

Steps to reproduce

  1. Turn on all debugging checks (range check, IO check, etc)
  2. Specialize TDeque on a "managed type", for instance a dynamic array.
  3. Create an instance of this type.
  4. Immediately free the instance without putting anything in it.
  5. Access violation.

Example Project

failing-deque.zip

program Project1;

uses gdeque, classes;

type
  myarr = array of integer;
  TSLDeque = specialize TDeque<myarr>;

var
  X: TSLDeque;
begin
  X := TSLDeque.Create;
  X.Free;

  writeln('yeah we did it');

  readln;
end.    

What is the current bug behavior?

TDeque attempts to run this function when it is destroyed:

procedure TDeque.ClearData;
var
  i: SizeUint;
begin
  if IsManagedType(T) then
    for i := Low(FData) to High(FData) do
      Finalize(FData[i]);
  FillChar(FData[Low(FData)], SizeUInt(Length(FData))*SizeOf(T), 0);
end;     

Notice that if the TDeque is empty, it will still attempt to execute the body of the for loop, meaning it will attempt to access FData[0] which is nil.

What is the expected (correct) behavior?

The TDeque should not index into nil in this case.

Relevant logs and/or screenshots

Possible fixes

See the above block of code. I'm not sure of the best way to solve this, but perhaps just a check to see if FData is nil or not before beginning the loop?