Searching for memory leak in C++ Builder XE4

598 views Asked by At

I'm trying to find and fix a memory leak that is present in my application. A memory analysis tool which i'm trialling - C++ Memory Validator - shows that there is 1,310,706 bytes being allocated approximately every 5 minutes. The call stack for these allocations are traced to what I think is the Embarcadero memory manager which is written in pascal. The function in question is:

{Allocates a new sequential feed medium block pool and immediately splits off a
 block of the requested size. The block size must be a multiple of 16 and
 medium blocks must be locked.}
function AllocNewSequentialFeedMediumPool(AFirstBlockSize: Cardinal): Pointer;
var
  LOldFirstMediumBlockPool: PMediumBlockPoolHeader;
  LNewPool: Pointer;
begin
  {Bin the current sequential feed remainder}
  BinMediumSequentialFeedRemainder;
  {Allocate a new sequential feed block pool}
  LNewPool := VirtualAlloc(nil, MediumBlockPoolSize, MEM_COMMIT, PAGE_READWRITE);
  if LNewPool <> nil then
  begin
    {Insert this block pool into the list of block pools}
    LOldFirstMediumBlockPool := MediumBlockPoolsCircularList.NextMediumBlockPoolHeader;
    PMediumBlockPoolHeader(LNewPool).PreviousMediumBlockPoolHeader := @MediumBlockPoolsCircularList;
    MediumBlockPoolsCircularList.NextMediumBlockPoolHeader := LNewPool;
    PMediumBlockPoolHeader(LNewPool).NextMediumBlockPoolHeader := LOldFirstMediumBlockPool;
    LOldFirstMediumBlockPool.PreviousMediumBlockPoolHeader := LNewPool;
    {Store the sequential feed pool trailer}
    PNativeUInt(PByte(LNewPool) + MediumBlockPoolSize - BlockHeaderSize)^ := IsMediumBlockFlag;
    {Get the number of bytes still available}
    MediumSequentialFeedBytesLeft := (MediumBlockPoolSize - MediumBlockPoolHeaderSize) - AFirstBlockSize;
    {Get the result}
    Result := Pointer(PByte(LNewPool) + MediumBlockPoolSize - AFirstBlockSize);
    LastSequentiallyFedMediumBlock := Result;
    {Store the block header}
    PNativeUInt(PByte(Result) - BlockHeaderSize)^ := AFirstBlockSize or IsMediumBlockFlag;
  end
  else
  begin
    {Out of memory}
    MediumSequentialFeedBytesLeft := 0;
    Result := nil;
  end;
end;

Note that the variable MediumBlockPoolSize is a constant which is the exact size of the leak.

What i think is happening is that as my application leaks memory, there will come a point where it allocates something at which point we request a new block of memory (1.3MB) from the pool of available memory, and I think this happens roughly every 5 mins. However, this doesn't tell me exactly where the leak is coming from. Is there any way I can better pinpoint the source of the leak?

I have gone through the code and made sure there are deletes for all news and that no pointers get reassigned without being deleted first etc.

Below is the call tree when the memory block is allocated. Note that if i comment out this call tree in the code, the block appears in a different location in my code, and so on and so on.

call tree

Thanks.

1

There are 1 answers

0
Remy Lebeau On

The Delphi/C++Builder RTL uses (a slimmed down version of) the FastMM memory manager by default. FastMM allocates memory in buckets, and reuses freed memory for future allocations instead of returning it back to the OS. Memory is not returned to the OS until the app terminates.

This is not a real leak, but your Validator doesn't know that, as it doesn't know how the RTL's memory manager actually uses allocated memory at runtime (this is the same reason why you can't use Windows Task Manager to diagnose leaks, either).

If you want to trace real leaks, install the full version of FastMM and use its own built-in leak detector functionality. Only the actual memory manager being used at runtime knows how memory is being used and can know for sure what constitutes a real leak or not.