title: GetMem, Pointers and Access Violations
body: <p>I'm struggling with some memory allocation and a frustratingly difficult to locate and fix exception whilst using XE2.  </p>
  
  <p>I have a factory class which creates and stores dynamically created objects for display on a form, but the factory creation fails in some cases. If i execute the following code as the first action after program launch then all is well - the memory is allocated nicely and all other functions work.  However, if i say open another form, or an open file dialog and then execute the factory creation there is an exception:</p>
  
  <pre><code>Exception EAccessViolation: Access violation at address 0040AA1F in module
  'UMTester.exe'. Write of address 00000069 (OS Exception)  Exception occurred at
  $0040AA1F (Module "System", Procedure "@DynArrayAsg", Unit "", Line 0)
  </code></pre>
  
  <p>The exception is always at the address 0040AA1F and the proc is always @DynArrayAsg.</p>
  
  <p>Although the factory will be created instantly at launch i don't want to ignore the bug as that would just be bad form!</p>
  
  <p>Here's the factory creation code:</p>
  
  <pre><code>constructor TFactory.Create(FactoryObjectClass : tclass;Capacity : integer);
  var nn : integer;
  fptr : pointer;
  fObj : TFactoryObject;
  begin
    fClass := FactoryObjectClass;
    fsize := fclass.InstanceSize;
    fdata:=nil;
  
    //Capacity represents the number of objects; trying to allocate small amounts 
    //of memory results in exceptions so i artificially increase it anything less 
    //than 20 throws an exception
    if Capacity&lt;19 then Capacity:=20;
  
    //This seems to reduce exceptions as the requested memory is in whole blocks 
    while frac((Capacity*SizeOf(Pointer))/4)&lt;&gt;0.0 do Inc(Capacity);
  
    fcapacity := Capacity;
  
    //Allocate memory
    getmem(fdata,fsize*fcapacity);
    getmem(fDatalist,sizeof(Pointer)*fcapacity);
    getmem(ffreelist,sizeof(Pointer)*fcapacity);
  
    fdatacount :=0;
    ffreecount :=0;
    fptr       := fdata;
  
    //create a pointer to the factory object at each memory address
    for nn := 0 to Capacity-1 do begin
     fdatalist[fdatacount]:= fptr;         &lt;------- Exception is always here
     fobj := Fclass.InitInstance(fptr) as TFactoryObject;
     fobj.factory := self;
     fObj.Create;
     fptr := pointer(integer(fptr)+fsize);
     inc(fDataCount);
    end;
  end;
  </code></pre>
  
  <p>The factories pointer list is instantiated from a TDictionary with basic form elements like labels, memo's and listboxes etc.</p>
  
  <pre><code>  procedure TObjs.Initialize(AObjs : TDict);
    var
     nn :integer;
     C : TRttiContext;
     T : TRttiInstanceType;
     V : TValue;
    begin
      //Process all objects requested
      for nn := 0 to AObjs.Count-1 do begin
        //Locate the class from the supplied reference in AObjs
        T := (C.GetType(TClass(FindClass(AObjs[nn]['Type']))) as TRttiInstanceType);
  
        //Invoke the creation of the object by calling its native constructor
        V := T.GetMethod('Create').Invoke(T.metaClassType,[Application]);
  
        //Adds each requested object to the repository and displays the object
        Objs[nn].SetValue(V.AsObject,AObjs[nn]);
      end;
    end;
  </code></pre>
  
  <p>Observations and Thoughts:</p>
  
  <ol>
  <li>Perhaps heap fragmentation means the requested memory of fDatalist means i can't get the whole amount in a contiguous block.  </li>
  <li>When creating the factory as the first action after pgm launch fDataList is always at address $1A9E2B0.  If i show another form first, then create the factory fDataList is created at $1A9DF98.  Some actions do not affect the address location, and no exception is ever thrown when fDataList is at address $1A9E2B0.  Nowhere am i assigning fDataList to a specific address, so heaven knows why it works at this address and not others.</li>
  <li>On the line "if Capacity&lt;19 then Capacity:=20;" if i change the 20 to 60 i can postpone the exception for longer, i.e i can execute an increased number of un-related procedures before creating the factory.  The exception always occurs though after a certain amount of usage.</li>
  </ol>
  
  <p>The factory is created once here:</p>
  
  <pre><code>  SetLength(Objs,AObjs.Count);
    AFactory := TFactory.Create(TchObj,AObjs.Count);
  
    //Initialize the full array of objects
    for Index := 0 to AObjs.Count -1 do
      Objs[Index] := Afactory.Request_obj as TchObj;
  </code></pre>
  
  <p>Class definition for TFactory is:</p>
  
  <pre><code>  TchFactory = class
      private
        fdata      : pointer;
        fsize      : integer;
        fDataList  : PPointerList;  // from classes unit
        fdatacount : integer;
        fFreeList  : PPointerList;
        fFreeCount : integer;
        fCapacity  : integer;
        fcLass     : TClass;
      public
        constructor Create(FactoryObjectClass : Tclass;Capacity : integer);
        destructor  Destroy;   override;
        function    Request_Obj : TchFactoryObject;
        procedure   Recycle(FactoryObject : TchFactoryObject);
      property Capacity  : integer read fCapacity;
      property CountUsed : integer read fdataCount;
      property CountFree : integer read fFreeCount;
    end;
  </code></pre>
  
  <p>What can i look at?<br>
  Any ideas on how i debug this?<br>
  Or am i just doing something insanely wrong?</p>
  
  <p><strong>EDIT:</strong>
  Removing the "trial and error" lines David refers to and changing GetMem to AllocMem fixes the issue.  So the final code for the factory constructor is:</p>
  
  <pre><code>constructor TchFactory.Create(FactoryObjectClass : tclass;Capacity : integer);
    var Index : integer;
    fptr : pointer;
    fObj : TchFactoryObject;
    begin
      fClass := FactoryObjectClass;
      fsize := fclass.InstanceSize;
  
      fcapacity := Capacity;
      fdata := AllocMem(fsize*fcapacity);
      fdatalist:= AllocMem(sizeof(Pointer)*fcapacity);
      fFreelist:= AllocMem(sizeof(Pointer)*fcapacity);
      fdatacount :=0;
      ffreecount :=0;
      fptr       := fdata;
  
      for index := 0 to Capacity-1 do begin
  
        fdatalist[fdatacount]:= fptr;
        fobj := Fclass.InitInstance(fptr) as TchFactoryObject;
        fobj.factory := self;
        fObj.Create;
        fptr := pointer(integer(fptr)+fsize);
        inc(fDataCount);
  
       end;      
    end;
  </code></pre>