TShellTreeView内存泄漏

时间:2016-01-27 18:20:14

标签: delphi memory-leaks delphi-xe8

我使用MadExcept来追踪内存泄漏。如果我在表单上放置一个TShellTreeView并运行应用程序MadExcept报告内存泄漏。只是打开和关闭,没有别的。我在XE8下使用XE6包,因为这是最后发布的AFAIK。

我知道以前的delphi版本存在一些问题,但我认为这些问题在XE6软件包中得到修复。

这是应用程序关闭后显示的MadExcept窗口:

MadExcept ScreenShot

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

是的,madExcept是正确的,因为它具有极高的质量。这确实是您使用的代码中的缺陷。它看起来像这样:

function CreateRootFolder(RootFolder: TShellFolder; OldRoot : TRoot;
  var NewRoot: TRoot): TShellFolder;
var
  P: PWideChar;
  NewPIDL: PItemIDList;
  NumChars,
  Flags,
  HR: LongWord;
  ErrorMsg : string;
begin
  HR := S_FALSE;
  if GetEnumValue(TypeInfo(TRootFolder), NewRoot) >= 0 then
  begin
    HR := SHGetSpecialFolderLocation(
            0,
            nFolder[GetCSIDLType(NewRoot)],
            NewPIDL);
  end
  else if Length(NewRoot) > 0 then
  begin
    if NewRoot[Length(NewRoot)] = ':' then NewRoot := NewRoot + '\';
    NumChars := Length(NewRoot);
    Flags := 0;
    P := StringToOleStr(NewRoot);
    HR := DesktopShellFolder.ParseDisplayName(0, nil, P, NumChars, NewPIDL, Flags);
  end;

  if HR <> S_OK then
  begin
    { TODO : Remove the next line? }
    // Result := RootFolder;
    ErrorMsg := Format( SErrorSettingPath, [ NewRoot ] );
    NewRoot := OldRoot;
    raise Exception.Create( ErrorMsg );
  end;

  Result := CreateRootFromPIDL(NewPIDL);
  if Assigned(RootFolder) then RootFolder.Free;
end;

在两个分支中,呼叫者有责任销毁NewPIDL。代码没有这样做。通过阅读文档可以看出这一点:

将函数的最后部分修改为:

Result := CreateRootFromPIDL(NewPIDL);
if Assigned(RootFolder) then RootFolder.Free;
CoTaskMemFree(NewPIDL);

我可以确认我已经测试了这个变化。我测试了原始代码并重现了您报告的泄漏。然后我按照上面的描述更改了代码,madExcept报告没有泄漏。

您无法实现同样意味着您没有执行修改后的代码。也许您正在使用运行时包,并且没有重新编译修改后的代码。或许还有另一种解释。无论如何,我完全清楚你没有删除泄漏是因为你仍在运行原始的未经修改的代码。