lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] Reference lifetime extension


From: Greg Chicares
Subject: [lmi] Reference lifetime extension
Date: Thu, 11 Oct 2018 20:31:12 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0

I had saved this little change off to the side, and was thinking of
committing it, but luckily it faulted when I tested it repeatedly:
  Unhandled exception: page fault on execute access to 0x068a9050 in 32-bit 
code (0x068a9050).
so I know it's wrong; but why, exactly?

---------8<--------8<--------8<--------8<--------8<--------8<--------8<-------
diff --git a/ledger_pdf.cpp b/ledger_pdf.cpp
index d3eb99c4..c83a0d3b 100644
--- a/ledger_pdf.cpp
+++ b/ledger_pdf.cpp
@@ -94,6 +94,6 @@ std::string write_ledger_as_pdf(Ledger const& ledger, 
fs::path const& filepath)
     if(0 == scaled_ledger.GetLedgerInvariant().ScalePower())
     scaled_ledger.AutoScale();
-    auto const pdf = ledger_pdf_generator::create();
-    pdf->write(scaled_ledger, pdf_out_file);
+    ledger_pdf_generator const& pdf = *ledger_pdf_generator::create();
+    pdf.write(scaled_ledger, pdf_out_file);
 
     return pdf_out_file.string();
--------->8-------->8-------->8-------->8-------->8-------->8-------->8-------

Here, create() is a callback to this member function:

    static std::shared_ptr<ledger_pdf_generator> do_create()
        {
        return std::make_shared<ledger_pdf_generator_wx>();
        }

and a postcondition of std::make_shared<>() is that get() is non-null,
so I infer that the lifetime of the temporary shared_ptr isn't extended
to the line after create() is called. And I reason that this is because
C++17 (N4659) says in 15.2 [class.temporary]:

| [6] The temporary to which the reference is bound or the temporary
| that is the complete object of a subobject to which the reference is
| bound persists for the lifetime of the reference except:
[...]
| [6.2] The lifetime of a temporary bound to the returned value in a
| function return statement (9.6.3) is not extended; the temporary is
| destroyed at the end of the full-expression in the return statement.

...so [15.2/6.2] is the exact explanation, right?

Somehow I still have great difficulty seeing at a glance why the patch
above is wrong. I guess I just try to avoid shared_ptr in general, and
assume that it always lengthens the lifetime of the object pointed to,
and I need to bear in mind that when a function returns a _temporary_
shared_ptr, that shared_ptr will expire at the next semicolon, and any
reference I had formed to it will be left dangling.

It that the whole explanation, or am I still missing something?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]