Hi guys,
We've been fixing a few resource leaks recently, and I suspect it would
pay to remind people of the documentation on VclPtr:
https://gerrit.libreoffice.org/gitweb?p=core.git;a=blob;f=vcl/README.lifecycle;h=6ef91ccfce51d4b5daeb7d03527f471233ae71ab;hb=HEAD
I guess I should update that now the transitional stuff is obsolete.
But here is the punch-line:
**** please call disposeAndClear() ****
or, use:
ScopedVclPtrInstance<Foo> aFoo(...);
which will do it for you when your variable goes out of scope.
* Wait but why ?
VclPtr is very much like a shared_ptr<> or any other such
smart-reference counting thing (it differs for only rather boring
reasons). What is different is VCL; so take for example this:
{
VclPtr<VirtualDevice> xDev(VirtualDevice::Create());
// VclPtrInstance<VirtualDevice> xDev; - its synonym.
... do something temporary with xDev ...
} // exit scope.
It looks safe, what could go wrong ? the smart pointer will go out of
scope, and xDev will be deleted - right ? it is not easy to see anyone
else taking a reference to xDev ... so ...
Beware - the reason is that VCL is infested with scads of lists of
internal smart pointers all to each other:
include/vcl/virdev.hxx
class VCL_DLLPUBLIC VirtualDevice : public OutputDevice {
private:
VclPtr<VirtualDevice> mpPrev;
VclPtr<VirtualDevice> mpNext;
Oh dear - each VirtualDevice is part of a manually maintained linked
list of safe but problematic VirtualDevices. And to add insult to injury
we have:
include/vcl/outdev.hxx
class VCL_DLLPUBLIC OutputDevice : public virtual VclReferenceBase {
private:
mutable VclPtr<OutputDevice> mpPrevGraphics; ...
mutable VclPtr<OutputDevice> mpNextGraphics; ...
So - each VirtualDevice is part of two doubly linked lists. Windows
(derived from OutputDevice) takes part in many more hierarchical
structures too ...
* Summary:
Calling dispose is a good plan ! =) This releases all of these
references, lists etc. and also frees any underlying resources - leaving
only an empty shell of an object around until the last object is released.
So:
{ // correct
VclPtrInstance<VirtualDevice> xDev;
... do something temporary with xDev ...
xDev.disposeAndClear()
}
Or better:
{ // correct
ScopedVclPtrInstance<VirtualDevice> xDev;
...
} // auto-disposes outside the scope.
* Why bother with a smart pointer then ?
So - since we have to replace what would be a 'delete' with a
disposeAndClear() anyway - why bother in the first instance ? the answer
here is that LibreOffice is quite good at getting deep call stacks
around even emission, referencing Windows and being sure that the Window
is still alive, and has a valid handle (so we can reliably check it is
alive) as we return through those makes life lots cleaner and easier.
The nice thing about vclptr is that you can call disposeAndClear several
times from different paths in different orders, and you can be sure that
if the pointer is not NULL it is always valid.
I hope that helps someone - very happy to help if anyone is in doubt etc.
ATB,
Michael.
--
michael.meeks@collabora.com <><, Pseudo Engineer, itinerant idiot
Context
- VclPtr a refresher ... · Michael Meeks
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.