Documentation/4.2/Developers/Tutorials/MemoryManagement

From Slicer Wiki
Revision as of 23:35, 1 November 2012 by Pieper (talk | contribs)
Jump to: navigation, search
Home < Documentation < 4.2 < Developers < Tutorials < MemoryManagement

From http://massmail.spl.harvard.edu/public-archives/slicer-devel/2011/007513.html

Like VTK, Slicer contains some "factory" methods:

- vtkMRMLScene::CreateNodeByClass()
- vtkMRMLScene::GetNodesByClass()
- ...

Like in C++, it means that the functions return an object with a reference count of 1 that nobody "owns" and the caller must take care of releasing the object to avoid memory leak.

While there is workaround for some methods ( slicer.mrmlScene.CreateNodeByClass('vtkMRMLModelNode') should be replaced by slicer.vtkMRMLModelNode() ) there is currently no automatic/clean mechanism to release the object created by such methods.

The only "hack" that exists for now is to decrease the reference count manually in your code:

nodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLLinearTransformNode')
nodes.UnRegister(slicer.mrmlScene)      # ----> (reference count was 2, keep 1 for the python reference)
...

In C++, the following would apply:

vtkCollection* nodes =
mrmlScene->GetNodesByClass("vtkMRMLLinearTransformNode");
...
nodes->Delete();

or using vtkSmartPointer:

vtkSmartPointer<vtkCollection> nodes;
nodes.TakeReference(mrmlScene->GetNodesByClass("vtkMRMLLinearTransformNode"));
...

Amendment from JC http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=19772

The reference count shouldn't be decreased using the naive approach where it is set to one. Indeed, internally, the reference count could be any number greater than one. It doesn't have to be 2.

Considering this last remark, using the following approach is *REQUIRED*, otherwise it will lead to a CRASH of the application.

n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
slicer.mrmlScene.addNode(n)
n.UnRegister(slicer.mrmlScene)

Even better, this specific example can be simplified using the following syntax, this is the *RECOMMENDED* approach, it will prevent bug, memory leaks and crashes:

 n = slicer.mrmlScene.addNode(slicer.vtkMRMLViewNode())

And if the name of the node is generated at runtime, this could be done:

 n = eval('slicer.mrmlScene.AddNode(slicer.%s())' % 'vtkMRMLViewNode')

Tracking Leaks

Csaba Pinter and Andras Lasso developed a windows tool for helping identify leaks. See their code in this repository. The code includes a How To file that describes usage and limitations.

_______________________________________________