|
Tags: 2017 source edit, Replaced |
(10 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.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')
| |