C++ 在C++;生成器XE4

C++ 在C++;生成器XE4,c++,memory-leaks,c++builder,c++builder-xe4,C++,Memory Leaks,C++builder,C++builder Xe4,我正在尝试查找并修复应用程序中存在的内存泄漏。内存分析工具,我是Trang-C++内存验证程序,显示大约有1310706字节被分配大约每5分钟。这些分配的调用堆栈可以追溯到我认为是用pascal编写的Embarcadero内存管理器。有关职能是: {Allocates a new sequential feed medium block pool and immediately splits off a block of the requested size. The block size m

我正在尝试查找并修复应用程序中存在的内存泄漏。内存分析工具,我是Trang-C++内存验证程序,显示大约有1310706字节被分配大约每5分钟。这些分配的调用堆栈可以追溯到我认为是用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;
{分配一个新的顺序馈送介质块池,并立即拆分
请求大小的块。块大小必须是16和的倍数
必须锁定中等块。}
函数AllocNewsSequentialFeedMediumPool(affirstBlockSize:Cardinal):指针;
变量
LOldFirstMediumBlockPool:PMediumBlockPoolHeader;
LNewPool:指针;
开始
{Bin当前顺序馈送余数}
二进制顺序输入剩余;
{分配新的顺序馈送块池}
LNewPool:=VirtualAlloc(nil、MediumBlockPoolSize、MEM\u COMMIT、PAGE\u READWRITE);
如果LNewPool为零,则
开始
{将此块池插入块池列表}
LOldFirstMediumBlockPool:=MediumBlockPoolsCircularList.NextMediumBlockPoolHeader;
PMediumBlockPoolHeader(LNewPool).PreviousMediumBlockPoolHeader:=@MediumBlockPoolsCircularList;
MediumBlockPoolsCircularList.NextMediumBlockPoolHeader:=LNewPool;
PMediumBlockPoolHeader(LNewPool).NextMediumBlockPoolHeader:=LOldFirstMediumBlockPool;
LOldFirstMediumBlockPool.PreviousMediumBlockPoolHeader:=LNewPool;
{存储顺序馈送池尾部}
PNativeUInt(PByte(LNewPool)+MediumBlockPoolSize-BlockHeaderSize)^:=IsMediumBlockFlag;
{获取仍然可用的字节数}
MediumSequentialFeedBytesLeft:=(MediumBlockPoolSize-MediumBlockPoolHeaderSize)-第一个块大小;
{获取结果}
结果:=指针(PByte(LNewPool)+MediumBlockPoolSize-AffirstBlockSize);
LastSequentialyFedMediumBlock:=结果;
{存储块头}
PNativeUInt(PByte(结果)-BlockHeaderSize)^:=第一个BlockSize或IsMediumBlockFlag;
结束
其他的
开始
{内存不足}
MediumSequentialFeedBytesLeft:=0;
结果:=无;
结束;
结束;
请注意,变量MediumBlockPoolSize是一个常数,它是泄漏的确切大小

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

我已经检查了代码,并确保所有新闻都有删除,并且在没有先删除的情况下没有指针被重新分配,等等

下面是分配内存块时的调用树。请注意,如果在代码中注释掉此调用树,则块将显示在代码中的不同位置,依此类推


谢谢。

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

这不是真正的泄漏,但您的验证器不知道这一点,因为它不知道RTL的内存管理器在运行时如何实际使用分配的内存(这也是您不能使用Windows任务管理器诊断泄漏的原因)

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