views:

118

answers:

3

I had created a small multi threaded application and I am trying to convert it to use OmniThreadLibrary. I am using the Virtualtreeview to display a log and the status/results. The Vst Log only has two columns and the record contains just two string fields (extremely simple, no objects inside the record).

Using a DEMO project that comes with OTL (thread pool #11) I changed the project to use a VirtualTreeview instead of the listbox. When I "Run Task" from the demo there is no memory leak, but if I run "Run Task" more than once a memory leak will occur. A memory leak will occur if I run any task more than once. If I do not use the VirtualTreeView at all, no memory leaks occur at any time. Just when I use the VST and when a task is run more than once.

I do use the FreeNode event and clear the strings, and even tried using Finalize...

example:

procedure TFormMain.vstLogFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  LogData: PTreeLogData;
begin
  LogData:=Sender.GetNodeData(Node);

  if Assigned(LogData) then begin
    LogData^.Msgtype := '';
    LogData^.Msg := '';
  end; 
  //Finalize(LogData^);

end;

why do I get a memory leak when a task is run more than once? Delphi 2010 with FastMM4 latest Virtualtreeview and OTL

+4  A: 

I don't know why that's happening specifically, but I know how you can find out: turn on FastMM's FullDebugMode. (You'll need to download the FastMM full version from SourceForge for this.) Turn on the option that gives you a memory leak report in a file, and make sure the project's generating a detailed map file. Once you've got this set up, instead of just a popup window, FastMM will give you a very detailed memory leak report, complete with stack traces. This should help you narrow down what's going on.

Mason Wheeler
+1  A: 

As Mason said, FastMM4 is your friend here. You may want to give a look at this CodeRage 2 session: Fighting Memory Leaks for Dummies. It mainly shows how to use FastMM to prevent/detect memory leaks in Delphi. Was for D2007 but still relevant.

As for why running twice does leak but not running once, from experience, it's mostly due to creating and storing an Object in a Field/Variable without checking first if it was assigned, leaking the previous reference. Construct like this:

TSomething
FMyObject: TMyObject;
[..]

TSomething.Destroy;
begin
  FMyObject.Free;
end;
[...]

//somewhere in code:
FMyObject := TMyObject.Create; //leaks the previous FMyObject

Obviously not as straightforward and probably hidden in some setters or through some kind of List/container... Here I'd guess adding to the VirtualTreeView without checking...

François
+3  A: 

The NodeFree event is only called for Validated nodes, validated usually means Nodes that are shown one or more times (when the GetText event was called). See Memory Leaks when using the Virtual TreeView Component

edit: you can confirm by checking your node count and counting the number of times the NodeFree event is called.

Remko
you are correct, if you put the following after you create the node the memory leaks are gone: "vst1.ValidateNode(aNode, False);" I have used ValidateNode when I updated nodes in a vst before, but I have never seen it used when you create the node... not in any demo and tutorial. Thanks.
Logman