Difference between revisions of "Documentation/Nightly/Developers/Tutorials/MemoryManagement"

From Slicer Wiki
Jump to: navigation, search
Line 16: Line 16:
 
The only "hack" that exists for now is to decrease the reference count
 
The only "hack" that exists for now is to decrease the reference count
 
manually in your code:
 
manually in your code:
nodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLLinearTransformNode')
+
 
nodes.UnRegister(slicer.mrmlScene)      # ----> (reference count was 2, keep 1 for the python reference)
+
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:
 
In C++, the following would apply:
vtkCollection* nodes =
+
vtkCollection* nodes =
mrmlScene->GetNodesByClass("vtkMRMLLinearTransformNode");
+
mrmlScene->GetNodesByClass("vtkMRMLLinearTransformNode");
...
+
...
nodes->Delete();
+
nodes->Delete();
  
 
or using vtkSmartPointer:
 
or using vtkSmartPointer:
vtkSmartPointer<vtkCollection> nodes;
+
vtkSmartPointer<vtkCollection> nodes;
nodes.TakeReference(mrmlScene->GetNodesByClass("vtkMRMLLinearTransformNode"));
+
nodes.TakeReference(mrmlScene->GetNodesByClass("vtkMRMLLinearTransformNode"));
...
+
...
  
 
Amendment from JC http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=19772
 
Amendment from JC http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=19772

Revision as of 15:03, 9 October 2012

Home < Documentation < Nightly < 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')