[fpc-pascal] fgl unit bug in generic class TFPGMap

Dennis Poon dennis at avidsoft.com.hk
Fri Oct 3 17:42:32 CEST 2014


I think I found a bug in TFPGMap.
Hope some of you can verify it.

The bug seems to relate to the binary search used in the method "FIND" 
but it does not occur for all string key values or at all capacity of 
the map. Seems only occur at the second item added and when it is 
certain string values.

I tried to debug it but cannot step into the codes of fgl unit so cannot 
find the cause.

Please help.

Dennis

=====================
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
   Classes,  Forms, Controls,StdCtrls, SysUtils,  fgl;
type

   TMapOfObjects=class(specialize TFPGMap < String, TObject> )
   public
     function Locate(TheKey : String) : Boolean;
     function GetContent  :String;
   end;

   TForm1 = class(TForm)
   public
     Map :  TMapOfObjects;
     Memo1 : TMemo;
     ButtonAdd : TButton;
     Edit1 : TEdit;
     N : integer;
     procedure ButtonAddClick(TheSEnder : TObject);
     destructor Destroy;override;
     constructor Create(TheOwner : TComponent);override;
   end;

var
   Form1: TForm1;

implementation

{$R *.lfm}

function TMapOfObjects.Locate(TheKey: String): Boolean;
var i  : integer;
begin
   result := false;
   for i := 0 to count-1 do begin
     if Keys[i] = TheKey then begin
       result := true;
       exit;
     end;
   end;
end;

procedure TForm1.ButtonAddClick(TheSEnder: TObject);
var idx : integer;
   L : TObject;
   s : String;
begin
   inc(n);
   L := TObject.Create;
   Map.Add(Edit1.Text, L);

   if not Map.Find(Edit1.Text, idx) then begin
     Memo1.lines.add('#'+IntToStr(n)+'   '+Edit1.Text+ ' was just added 
but cannot be found by method "FIND" ! BUG!');
     if Map.Locate(Edit1.Text) then begin
       Memo1.lines.add('         BUT a simple loop of comparision can 
locate it, proving the item was added, just the method "FIND" is  BUGGY!');
       Memo1.lines.add('         List content = '+Map.GetContent);
     end;
   end else begin
     Memo1.lines.add('#'+IntToStr(n)+'   '+Edit1.Text+ ' was added and 
found as expected');
     Memo1.lines.add('         List content = '+Map.GetContent);
   end;
end;

destructor TForm1.Destroy;
var i : integer;
begin
   for i := 0 to map.count-1 do
     Map.Data[i].Free;
   Map.Free;
   inherited Destroy;
end;

constructor TForm1.Create(TheOwner: TComponent);
begin
   inherited Create(TheOwner);

   ButtonAdd := TBUtton.Create(self);
   ButtonAdd.Parent := self;
   ButtonAdd.Left := 10;
   ButtonAdd.Top := 5;
   ButtonAdd.Caption := 'Add';
   ButtonAdd.OnClick := @ButtonAddClick;

   Edit1 := TEdit.Create(SELF);
   Edit1.Parent := self;
   Edit1.Top := 10;
   Edit1.Left := 100;
   Edit1.Text := '';

   Memo1:= TMemo.Create(self);
   Memo1.Parent := self;
   Memo1.Left := 16;
   Memo1.Height := 342;
   Memo1.Top := 74;
   Memo1.Width := 575;
   Memo1.lines.Clear;

   Map := TMapOfObjects.Create;

   //no matter what I set below, the same bug will appear. also, 
duplicates are always added
//  Map.Duplicates:= dupError;
//  Map.Duplicates:= dupIgnore;

   n := 0;
   Edit1.Text := 'abc';
   ButtonAddClick(nil);

   Edit1.Text := 'HHIV4'; //will trigger bug;
//  Edit1.Text := 'defv4'; //but strangely if add 'defv4' wont' trigger bug
   ButtonAddClick(nil);

   Edit1.Text := 'ghiV4';  //bug seems to disappear after the 2nd item 
is added. perhaps the buy is in binary search
   ButtonAddClick(nil);
end;

function TMapOfObjects.GetContent: String;
var i :Integer;
begin
   result := '';
   for i := 0 to count-1 do begin
     result := result+Keys[i]+',';
   end;
end;

end.




More information about the fpc-pascal mailing list