I'm currently learning C++ to be able to do meaningful contributions to OpenMW, so I've been reading a lot of code, and a couple of books on the topic.
But it's in Effective C++, by Scott Meyers, Item 17, that I found the most amazing trigger-happy footgun example:
processWidget(std::shared_ptr<Widget>(new Widget), priority());
std::shared_ptr
is a
reference counting
implementation: it will automatically destroy the object it owns when there is
no more std::shared_ptr
owning it.
Yet this code can result in a memory leak.
At first, I thought about a weird interaction between std::shared_ptr
and
new
, when the constructor of Widget
fails, but this case is handled
by the C++ runtime.
The first trick here is that function parameters evaluation order is unspecified,
meaning that new Widget
might be called, then priority()
, then the value
returned by new Widget
is passed to std::shared_ptr<Widget>(…)
.
The second one is there since this is C++, priority()
might raise an exception,
meaning that new Widget
will be called, but never passed to
std::shared_ptr
, and thus never deleted!
As AnyOldName3 added after reading this
blogpost, this might be why there is std::make_shared
,
with std::make_shared<Widget>()
being kinda equivalent to std::shared_ptr<Widget>(new Widget)
.
edit: Made it to hackernews' frontpage, with a web server running on 64MiB of ram and a single core.