我正在使用MadExcept来跟踪内存泄漏。如果将TShellTreeView放在窗体上并运行应用程序,则MadExcept将报告内存泄漏。只需打开和关闭,别无其他。我正在XE8下使用XE6软件包,因为这是AFAIK发行的最后一个。

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

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

delphi - TShellTreeView内存泄漏-LMLPHP

有任何想法吗?

最佳答案

是的,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是呼叫者的责任。该代码不这样做。可以通过阅读文档来了解这种情况:


SHGetSpecialFolderLocation
IShellFolder::ParseDisplayName


修改功能的最后部分如下:

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


我可以确认我已经测试了此更改。我测试了原始代码,并复制了您报告的漏洞。然后,我如上所述更改了代码,并且madExcept报告没有泄漏。

您无法达到相同的目的意味着您不执行修改后的代码。也许您正在使用运行时软件包,但尚未重新编译修改后的代码。也许还有另一种解释。无论如何,对我来说完全清楚的是,您未能消除漏洞是因为您仍在运行原始的未修改代码。

关于delphi - TShellTreeView内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35045105/

10-09 01:45