Memory Leaks when using the Virtual TreeView Component

Again a about post about using the Virtual TreeView component (did I mention it’s brilliant?), this time I will talk about memory leaks.

I often use Records to hold the treedata, and usually the record holds some string data (eg a caption) and an (a reference to) an Interface or Object(List) that holds more data.

If you are familiar with Virtual Tree then you know that you must can the NodeData in the OnFreeNode event.

Let’s look at an example:

Looks allright doesn’t it? And still if you test for memoryleaks with Eurekalog or FastMM you will sometimes notice some leaks.

This happens because Virtual Treeview only calls the OnNodeFree event for Validated Nodes and a node that was never “touched” (eg the node was never visible and thus the GetText event was never called) was never validated.

In these cases you can manually validate the node when adding it

Leave a Reply

  1. I too love that treeview component and was unaware of the need to have a node validated for that event to be called. Time to check a lot of code to be sure :) Thanks for the tip!

  2. That if you add the node using vt.insertnode,

    but what if the node creation purely virtual such and in example . like using initnode init child and so on ?

  3. This doesn’t make sense. If node is added using AddChild or InsertNode then it is automatically validated (initialized) at least from what I tested.

    And VT doesn’t call FreeNode for nodes that haven’t been initialized because they don’t consume memory so there is nothing to free – NodeDataSize is just size of the structure but it doesn’t allocate it right away. So if it is virtual, it doesn’t consume memory – it only knows how much memory it will allocate once it validates (initializes) node but doesn’t allocate it right away only when this is needed.

    However, if you use AddChild, then it doesn’t become virtual at all – because it initializes node.

    So ValidateNode call would be equivalent of initializing node (regardless if it is needed or not) and then removing it (deallocating) later.

    It all depends how you initialize node – on demand using OnNodeInit event or initially in the look for example by using AddChild.

    Try this: Add 100.000 nodes which are read from disk and scroll the list. If they are all initialized and validated you will scroll the list smoothly and there won’t be any OnNodeInit call. If this is the case then all 100.000 will receive OnFreeNode call when they are removed. If however there are OnNodeInit calls then it is virtual and the scroll won’t be smooth (as it will be reading items from disk) and it will also call OnNodeInit event.