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

From Slicer Wiki
Jump to: navigation, search
(4.0 -> 4.1)
 
Line 17: Line 17:
 
manually in your code:
 
manually in your code:
 
nodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLLinearTransformNode')
 
nodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLLinearTransformNode')
nodes.SetReferenceCount(1)      # ----> (was 2, keep 1 for the python
+
nodes.UnRegister(slicer.mrmlScene)      # ----> (reference count was 2, keep 1 for the python reference)
reference)
 
 
...
 
...
  
Line 43: Line 42:
 
  n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
 
  n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
 
  slicer.mrmlScene.addNode(n)
 
  slicer.mrmlScene.addNode(n)
  n.SetReferenceCount(n.GetReferenceCount() - 1)
+
  n.UnRegister(slicer.mrmlScene)
  
 
Even better, this specific example can be simplified using the following
 
Even better, this specific example can be simplified using the following

Revision as of 14:57, 9 October 2012

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