Jeff Overcash (TeamB) wrote:
> Charles Jensen wrote: >> I'm having a problem with memory leaks after updating (several) projects from XE2 to XE3. >> >> Clearly visible when ReportMemoryLeaksOnShutdown is enabled. => It seems to be related to using TIBQuery. >> >> Could it be because memory is allocated with GetMem/ReAllocMem (in IBAlloc) and freed by "FreeRecordBuffer" by setting the pointer to nil? >> >> - Charles > > Yes that is a leak. change it to > > procedure TIBCustomDataSet.FreeRecordBuffer(var Buffer: TRecordBuffer); > begin > if Assigned(Buffer) then > ReallocMem(Buffer, 0); > end; > > and statically link IBCustomDataset.pas to your app (Might need IBQuery.pas too). > > For most of XE3's beta TRecordBuffer at the db.pas level was defined as > Array<byte> so was allocated with SetLength and deallocated with setting it to > nil. Very late in the beta it was switched back to a pointer and this line was > missed (Actually someone on the dev team switched it back for me and I just > verified changes, this didn't change cause they missed it so I didn't catch it > either, still my fault). >
found two more going through the code. Also change
destructor TIBCustomDataSet.Destroy; begin
Close; FreeAndNil(FDataLink); FreeAndNil(FBase); ClearBlobCache; FreeAndNil(FBlobStreamList); FreeMem(FBufferCache, 0); FreeAndNil(FGeneratorField); FreeMem(FOldBufferCache, 0); FCacheSize := 0; FOldCacheSize := 0; FMappedFieldPosition := nil;
inherited Destroy; end;
and
procedure TIBCustomDataSet.InternalClose; begin if Assigned(Transaction) then Transaction.CheckAutoStop;
{note - to not raise an exception if the conenction is lost before destroying the object, only close it if it is not being destroyed. If it is being destroyed the IBSQL will be cleaned up normally when it is destroyed} if not (csDestroying in ComponentState) then FQSelect.Close; ClearBlobCache;
FreeRecordBuffer(FModelBuffer); FreeRecordBuffer(FOldBuffer); FreeRecordBuffer(FTempBuffer); FCurrentRecord := -1; FOpen := False; FRecordCount := 0; FDeletedRecords := 0; FRecordSize := 0; FBPos := 0; FOBPos := 0; FCacheSize := 0; FOldCacheSize := 0; FBEnd := 0; FOBEnd := 0; if Assigned(FBufferCache) then ReallocMem(FBufferCache, 0); if Assigned(FOldBufferCache) then ReallocMem(FOldBufferCache, 0);
FUpdatesPending := false; if not (csDestroying in ComponentState) then begin BindFields(False);
if DefaultFields then DestroyFields; end; end;
-- Jeff Overcash (TeamB) (Please do not email me directly unless asked. Thank You) And so I patrol in the valley of the shadow of the tricolor I must fear evil. For I am but mortal and mortals can only die. Asking questions, pleading answers from the nameless faceless watchers that stalk the carpeted corridors of Whitehall. (Fish)