3
votes

I'm using MadExcept to trace memory leaks. If I put a TShellTreeView on a form and run the application MadExcept reports a memory leak. Just opening and closing, nothing else. I am using the XE6 package under XE8, since this is the last one released AFAIK.

I know there were some problems with former delphi versions, but these are fixed in the XE6 package, I think.

This is the MadExcept Window shown after app shutdown:

MadExcept ScreenShot

Any ideas?

1

1 Answers

3
votes

Yes, madExcept is correct which is to be expected because it is of exceptionally high quality. This is indeed a defect in the code you use. It looks like this:

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;

In both branches, it is the responsibility of the caller to destroy NewPIDL. The code does not do so. That this is so can be discerned by reading the documentation:

Amend the final part of the function to be like so:

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

I can confirm that I have tested this change. I tested the original code and reproduced the leak that you reported. I then changed the code as described above and madExcept reports no leak.

That you have been unable to achieve the same means that you are not executing the modified code. Perhaps you are using runtime packages and have not recompiled the modified code. Or perhaps there is another explanation. Anyway, it is completely clear to me that your failure to remove the leak is because you are still running the original unmodified code.