[vtkusers] Understanding vtkSmartPointers

Marcus D. Hanwell marcus.hanwell at kitware.com
Mon May 28 10:12:24 EDT 2018


On Mon, May 28, 2018 at 7:43 AM, Fcs <ftpronk at engits.com> wrote:

> Using VTK for one of our projects, we are encountering some memory leaks
> which, in time, cripple our system.  So I'm trying to have a better
> understanding of the  VTK pointers
> <https://blog.kitware.com/a-tour-of-vtk-pointer-classes/>  .
>
> It was my (erroneous..?) belief that the *vtkSmartPointer*s would destroy
> the object they were holding when getting out of scope.  Carefully reading
> the kitware blog post linked hereinabove, and playing around with a test
> code (code sample below), I now understand that it is objects held by
> *vtkNew* that will be destroyed when out-of-scope, and that
> *vtkSmartPointer*s, on the contrary, will keep them alive as long as the
> reference count is non-zero.  Is this correct?
>

No, that is not correct. The vtkNew class instantiates a vtkObject derived
instance and will decrement its reference count when it goes out of scope.
You can still store what was created by vtkNew in a vtkSmartPointer,
increasing the reference count to two, and keeping that object alive even
when the containing vtkNew goes out of scope.

In its simplest form, if you don't use other smart pointer classes with it
then vtkNew acts much like a stack allocated object, where the object
created is automatically deleted when it goes out of scope. You must
remember that all vtkObject derived classes are implicitly reference
counted - it is built into the API. The smart pointer classes just take
care of incremementing/decrementing the reference count.

>
> Now, from a practical point of view:  does this mean that I can, in a
> class,
> create an entire VTK pipeline with *vtkSmartPointer*s, and only store the
> latest object in a member variable to keep every object alive (So, in my
> code below, only bookkeep the object returned by applyFilters())?  And that
> when I'm finished, I can call ->Delete() on that object to clean-up the
> entire pipeline?  Is this a good practice?  Until now, I was painstakingly
> storing every object created for the lifetime of a pipeline, and I would
> like to know if I can simplify my code..
>
> In my opinion you should aim to never call Delete, but to have a smart
pointer contain the things needed. I think all pipeline API will increase
the reference count, and so you only usually need to keep a reference to
the pipeline objects you are going to keep around/use. The debug leaks code
will help you verify you got it right.

I would add that we have found in bigger applications that a passing debug
leaks is not always enough, ensuring objects are deleted when they are done
with is more difficult but necessary, especially in graphical applications
that might run for some time. My honest summary of using the smart pointers
(in classes, local code, etc) is:

vtkNew - when you will instantiate the object, and want to keep a strong
reference (you can't change what instance a vtkNew variable points to)

vtkSmartPointer - when you might create, or use an instance passed in, and
ensure it stays around for when you want to make calls. Assigning a
different instance to one will decrement the one it points to before
switching it to point to the new instance and incrementing.

vtkWeakPointer - when you want to call API if something is still around,
check for nullptr before using, will not affect reference count.

I think I wrote something similar back then. Whenever I see code like

vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();

I want to replace it with

vtkNew<vtkRenderer> renderer;

It does the exact same thing with no repetition, and is clearer. The
examples require backwards compatibility with older VTK, and I don't think
Bill liked calling .GetPointer()/.Get() on the vtkNew object. You no longer
have to do that, but it is a more recent addition to the vtkNew API - it
will implicitly return the pointer to the contained object as
vtkSmartPointer does.

Hopefully this makes things a little clearer. At the end of the day all
vtkObject derived classes (read most of the vtk* classes) are implicitly
reference counted, the choice of vtkNew/vtkSmartPointer should be made
depending upon how those instances will be used in your code - both will
decrement the reference count by one when they go out of scope.

Marcus
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://vtk.org/pipermail/vtkusers/attachments/20180528/d073f985/attachment.html>


More information about the vtkusers mailing list