Forum > General
TFPList
Pasqualish:
I am looking at the code defined in ../rtl/objpas/classes/classesh.inc for an TFPList class, in the situation when FPC_TESTGENERICS is false. I don't understand how it works as it has a private member - FList: PPointerList - which is a pointer to a static array - array[0..MaxListSize - 1] of Pointer; However, there is no constructor for this class. I don't see how FList gets a valid value or what it points to would be created.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---TypePPointerList = ^TPointerList;TPointerList = array[0..MaxListSize - 1] of Pointer; TFPList = class(TObject) private FList: PPointerList; FCount: Integer; FCapacity: Integer; procedure CopyMove (aList : TFPList); procedure MergeMove (aList : TFPList); procedure DoCopy(ListA, ListB : TFPList); procedure DoSrcUnique(ListA, ListB : TFPList); procedure DoAnd(ListA, ListB : TFPList); procedure DoDestUnique(ListA, ListB : TFPList); procedure DoOr(ListA, ListB : TFPList); procedure DoXOr(ListA, ListB : TFPList); protected function Get(Index: Integer): Pointer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} procedure Put(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} procedure SetCapacity(NewCapacity: Integer); procedure SetCount(NewCount: Integer); Procedure RaiseIndexError(Index: Integer); public Type TDirection = (FromBeginning, FromEnd); destructor Destroy; override; Procedure AddList(AList : TFPList); function Add(Item: Pointer): Integer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} procedure Clear; procedure Delete(Index: Integer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} class procedure Error(const Msg: string; Data: PtrInt); procedure Exchange(Index1, Index2: Integer); function Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} function Extract(Item: Pointer): Pointer; function First: Pointer; function GetEnumerator: TFPListEnumerator; function IndexOf(Item: Pointer): Integer; function IndexOfItem(Item: Pointer; Direction: TDirection): Integer; procedure Insert(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} function Last: Pointer; procedure Move(CurIndex, NewIndex: Integer); procedure Assign (ListA: TFPList; AOperator: TListAssignOp=laCopy; ListB: TFPList=nil); function Remove(Item: Pointer): Integer; procedure Pack; procedure Sort(Compare: TListSortCompare); procedure ForEachCall(proc2call:TListCallback;arg:pointer); procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer); property Capacity: Integer read FCapacity write SetCapacity; property Count: Integer read FCount write SetCount; property Items[Index: Integer]: Pointer read Get write Put; default; property List: PPointerList read FList; end;
Thaddy:
The constructor is the default constructor for TObject which will initialize the structure.
Ultimately the ppointerlist is expanded on demand through ultimately setcapacity.
The capacity is checked and expanded/initialized when you add an Item to the list.
Hence the code is always valid.
Pasqualish:
Thanks!
I don't understand why the pointer type is defined to point to a static array as it doesn't appear that there is any limitation with regard to going past a static array bound. Although it does indirectly show what the allocation/re-allocation checks for as far as a size limit before raising an exception, so maybe it is for documentation.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$R+} type SomeArrayType = array [0 .. 1000] of Pointer; PSomeArrayType = ^SomeArrayType; var myPointer : PSomeArrayType; i : Cardinal;begin New(myPointer); for i := 0 to 2000 do Inc(myPointer); WriteLn('program ended normally');end.
outputs:
--- Quote ---program ended normally
--- End quote ---
Thaddy:
There are TWO big limitations: memory and stackspace.
If you would allocate a full array as TArray you either run out of memory or you blow up the stack. That's why they are PArray's or even PPArrays. The full size never gets used because you will probably run out of memory or blow up the stack long before hand. If you look in the implementation in Lists.inc you see what I mean.
This is normal and prudent programming procedure and this is also how it works in e.g. C and C++.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure BlowStack;var Arr:array[0.maxint-1] of pointer;begin Result :=0;end; type TMaxArray = array[0..maxint-1] of pointer; PMaxArray = ^TMaxArray;procedure DontBlowStack;var arr: PMaxArray;begin result := 0;end;
Thaddy:
--- Quote ---it doesn't appear that there is any limitation with regard to going past a static array bound
--- End quote ---
Of course there is: Its called Range checking and Stack checking. What you want can only work if range checks are off and inside a method when stack checking is also off.
But this is an often used programming technique (good or bad!)
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$RANGECHECKS OFF} TMyArray = array[0..0] of integer;// works only with range checks off in any meaningful wayPMyArray = ^TMyArray;// Now try any index other than 0 with {$R+} or {$RANGECHECKS ON}http://www.freepascal.org/docs-html/current/prog/progsu65.html#x72-710001.2.65
http://www.freepascal.org/docs-html/current/prog/progsu115.html#x123-1240001.3.32
Navigation
[0] Message Index
[#] Next page