在C ++ Builder XE4中搜索内存泄漏

时间:2018-03-16 14:40:12

标签: c++ memory-leaks c++builder c++builder-xe4

我正在尝试查找并修复应用程序中存在的内存泄漏。我试用的内存分析工具--C ++ Memory Validator - 显示大约每5分钟分配1,310,706个字节。这些分配的调用栈可以追溯到我认为用pascal编写的Embarcadero内存管理器。有问题的功能是:

{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;

请注意,变量MediumBlockPoolSize是一个常量,它是泄漏的确切大小。

我认为正在发生的事情是,当我的应用程序泄漏内存时,它会分配一些东西,此时我们从可用内存池中请求一个新的内存块(1.3MB),我认为这大约每5分钟发生一次。但是,这并没有告诉我泄漏的确切来源。有什么方法可以更好地查明泄漏的来源吗?

我已经完成了代码并确保删除了所有新闻,并且没有指针被重新分配而没有先被删除等。

下面是分配内存块时的调用树。请注意,如果我在代码中注释掉这个调用树,则该块会出现在我的代码中的其他位置,依此类推。

call tree

感谢。

1 个答案:

答案 0 :(得分:1)

默认情况下,Delphi / C ++ Builder RTL使用FastMM memory manager(精简版)。 FastMM在存储桶中分配内存,并重用已释放的内存以供将来分配,而不是将其返回给操作系统。在应用程序终止之前,内存不会返回到操作系统。

这不是真正的泄漏,但你的Validator不知道,因为它不知道RTL的内存管理器在运行时实际上如何使用已分配的内存(这也是同样的原因)您也无法使用Windows任务管理器来诊断泄漏。

如果要跟踪真正的泄漏,请安装完整版的FastMM并使用其自己的内置检漏仪功能。只有在运行时使用的实际内存管理器知道如何使用内存,并且可以确定是什么构成真正的泄漏。