|
Tags: 2017 source edit, Replaced |
| (11 intermediate revisions by 3 users not shown) |
| Line 1: |
Line 1: |
| − | From http://massmail.spl.harvard.edu/public-archives/slicer-devel/2011/007513.html
| + | <noinclude>{{documentation/versioncheck}}</noinclude> |
| | | | |
| − | Like VTK, Slicer contains some "factory" methods:
| + | {{documentation/banner |
| − | - vtkMRMLScene::CreateNodeByClass() | + | | text = [https://slicer.readthedocs.io/en/latest/developer_guide/advanced_topics.html#memory-management This page has been moved to read-the-docs.] |
| − | - vtkMRMLScene::GetNodesByClass()
| + | | background-color = 8FBC8F }} |
| − | - ...
| |
| − | 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.SetReferenceCount(1) # ----> (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.SetReferenceCount(n.GetReferenceCount() - 1)
| |
| − | | |
| − | 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')
| |