[vtkusers] Understanding vtkSmartPointers
Marcus D. Hanwell
marcus.hanwell at kitware.com
Wed May 30 11:07:30 EDT 2018
Hi Andrew,
To the best of my knowledge the examples require backward compatibility,
and so I couldn't show the "best" form for people who dislike calling
.Get() until the minimum is bumped to VTK 8.1.0 I think. Most of my work is
done on that, or even more recent SHAs, so I don't think about it too much.
Is there an answer for this, can we make an example that requires 8.1+, as
we add more new features it seems like a reasonable request. I am really
swamped right now, but was hoping to get to some charting examples too.
Thanks,
Marcus
On Tue, May 29, 2018 at 6:39 PM, Andrew Maclean <andrew.amaclean at gmail.com>
wrote:
> Hi Marcus,
> This is a very clear and succinct explanation of the usage of
>
> vtkNew /
>
> vtkSmartPointer /
>
> vtkWeakPointer .
> If you have time would it be possible to do a nice C++11 demonstration
> example to be added into VTK Examples?
> I have a suspicion that this will be an issue arising again and again.
>
> I'll be glad to help.
>
> Personally (like Bill) I have never liked: .GetPointer()/.Get() in
> vtkNew so I haven't used it much. However ... since it implicitly returns
> the pointer now, I'll probably use it more.
>
> Rgeards
> Andrew
>
>
>
>>
>>
>> ---------- Forwarded message ----------
>> From: "Marcus D. Hanwell" <marcus.hanwell at kitware.com>
>> To: Fcs <ftpronk at engits.com>
>> Cc: VTK Users <vtkusers at vtk.org>
>> Bcc:
>> Date: Mon, 28 May 2018 10:12:24 -0400
>> Subject: Re: [vtkusers] Understanding vtkSmartPointers
>> 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
>>
>>
>>
>> ---------- Forwarded message ----------
>> From: David Thompson <david.thompson at kitware.com>
>> To: "Marcus D. Hanwell" <marcus.hanwell at kitware.com>
>> Cc: Fcs <ftpronk at engits.com>, VTK Users <vtkusers at vtk.org>
>> Bcc:
>> Date: Mon, 28 May 2018 10:30:06 -0400
>> Subject: Re: [vtkusers] Understanding vtkSmartPointers
>> > ...
>> > 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;
>>
>> With c++11, you can also say
>>
>> auto renderer = vtkSmartPointer<vtkRenderer>::New();
>>
>> which cleans up the smart-pointer case a little bit.
>>
>> David
>>
>>
>>
>>
>> ---------- Forwarded message ----------
>> From: "Marcus D. Hanwell" <marcus.hanwell at kitware.com>
>> To: David Thompson <david.thompson at kitware.com>
>> Cc: Fcs <ftpronk at engits.com>, VTK Users <vtkusers at vtk.org>
>> Bcc:
>> Date: Mon, 28 May 2018 10:50:35 -0400
>> Subject: Re: [vtkusers] Understanding vtkSmartPointers
>> On Mon, May 28, 2018 at 10:30 AM, David Thompson <
>> david.thompson at kitware.com> wrote:
>>
>>> > ...
>>> > 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;
>>>
>>> With c++11, you can also say
>>>
>>> auto renderer = vtkSmartPointer<vtkRenderer>::New();
>>>
>>> which cleans up the smart-pointer case a little bit.
>>>
>>> For sure, although in the case of class member variables it doesn't
>> help, and I would argue vtkNew is cleaner (and vtkNew still uses far fewer
>> characters, you got to preserve the finite resources on disk :P ).
>>
>>
>>
>> ---------- Forwarded message ----------
>> From: Fcs <ftpronk at engits.com>
>> To: vtkusers at vtk.org
>> Cc:
>> Bcc:
>> Date: Mon, 28 May 2018 08:45:51 -0700 (MST)
>> Subject: Re: [vtkusers] Understanding vtkSmartPointers
>> Dear Mathieu, Marcus and David, thank you for your replies and tips, with
>> a
>> special thank to Marcus for his extensive explanations which really
>> clarified a few of the subtleties of the VTK pointers.
>>
>> Marcus, I had few extra questions linked to your reply.
>>
>>
>> > I In my opinion you should aim to never call Delete, but to have a smart
>> > pointer contain the things needed.
>>
>> Is there any danger in calling Delete()? The case I had in mind was to
>> perhaps free the memory occupied by a big structured/unstructured grid
>> object which would need to live until a sub-grid is extracted from it.
>>
>>
>> > 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.
>>
>> How good is the guarantee that this will work? "I think" and "usually"
>> seem
>> to imply that my mileage might vary on this one.. :-) Does it mean that
>> this should work in general, but that perhaps some exotic or slightly
>> buggy
>> newer features might not behave correctly? The use case I'm trying to
>> implement has a variable number of pre-definied filters which I'm chaining
>> together. If I test all the possible combinations, and they work, do I
>> have
>> the guarantee they will always work?
>>
>>
>> > 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.
>>
>> Does this not imply that every vtkObject created should be stored and
>> deleted manually afterwards? Or are there other ways to detect living
>> vtkObjects when you don't have a direct member variable pointing to it?
>> (say, like the vtkPlane created in applyFilters() in my example code..)
>>
>>
>> > 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.
>>
>> Good to know! Starting from which version is the call to
>> .GetPointer()/.Get() no longer needed? We are developing in vtk 6 at the
>> moment, but we should update to a new version at some point in the near
>> future.
>>
>> Kind regards,
>>
>> Francois.
>>
>>
>>
>>
>>
>>
>> --
>> Sent from: http://vtk.1045678.n5.nabble.com/VTK-Users-f1224199.html
>>
>> _______________________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at http://www.kitware.com/
>> opensource/opensource.html
>>
>> Please keep messages on-topic and check the VTK FAQ at:
>> http://www.vtk.org/Wiki/VTK_FAQ
>>
>> Search the list archives at: http://markmail.org/search/?q=vtkusers
>>
>> Follow this link to subscribe/unsubscribe:
>> https://vtk.org/mailman/listinfo/vtkusers
>>
>
>
> --
> ___________________________________________
> Andrew J. P. Maclean
>
> ___________________________________________
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://public.kitware.com/pipermail/vtkusers/attachments/20180530/fea886b1/attachment.html>
More information about the vtkusers
mailing list