Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: "Metzger, Markus T" <markus.t.metzger@intel.com>,
	       "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Subject: Re: [PATCH 1/3] Introduce gdb::unique_ptr
Date: Tue, 11 Oct 2016 10:23:00 -0000	[thread overview]
Message-ID: <ac1fe3e9-069c-a26e-e790-438b6ff3d3e9@redhat.com> (raw)
In-Reply-To: <A78C989F6D9628469189715575E55B233FFE47AC@IRSMSX104.ger.corp.intel.com>

On 10/11/2016 07:47 AM, Metzger, Markus T wrote:
>> -----Original Message-----
>> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
>> owner@sourceware.org] On Behalf Of Pedro Alves
>> Sent: Monday, October 10, 2016 6:47 PM
>> To: gdb-patches@sourceware.org
>> Subject: [PATCH 1/3] Introduce gdb::unique_ptr
> 
> Hello Pedro,

Hi Markus,

> 
>> Many make_cleanup uses in the code base are best eliminated by using a
>> "owning" smart pointer to manage ownership of the resource
>> automatically.
>>
>> The question is _which_ smart pointer.
>>
>> We have std::auto_ptr in C++03, but, as is collective wisdom by now,
>> that's too easy to misuse, and has therefore been deprecated in C++11
>> and finally removed in C++17.
> 
> Would it make sense to switch to C++11, instead?  

I think it would make a lot of sense to switch to C++11.  I'd love
that.  rvalue references support, move-aware containers, "auto",
std::unique_ptr and std::shared_ptr would be all very nice to have.

The only question in my mind is -- are people OK with requiring
gcc 4.8 or later?

I think gcc 4.8 or newer were available in Fedora 20.  I believe
Ubuntu 12.04 had it available as an option.  On older RHEL systems, 
it's available in DTS.

On older systems, you'd need to compile a newer gcc or clang first
before building gdb.  Would people find that acceptable?  Or put
another way, would anyone find that unacceptable?

But meanwhile, I don't want C++ conversion to be blocked
by that.  Hence this new shim.

Even if we don't require C++11, I think it'd make sense to compile
in C++11 mode if we have a capable compiler.  I.e., if you have
gcc 4.8 or newer, pass -std=gnu++11/-std=gnu++0x if necessary.

> Or delay this work until we can make this move?

No, I don't think so.  I think we need _some_ owning smart pointer.

An alternative is some separate RAII object that destroys a pointer
when leaving a scope:

  template <class T>
  struct cleanup_pointer
  {
    explicit cleanup_pointer(T *p) : m_ptr (p) {}
    cleanup_pointer { if (m_ptr != NULL) delete m_ptr; }
    void discard () { m_ptr = NULL; }
    T *m_ptr;
  };

  // Document that this returns a new object that must
  // be released with "delete".
  struct foo *function_returning_new_ptr ();

  // Document that this uses P, ownership is still with the caller.
  // May throw.
  void foo (struct foo *p);

  // Document that P is no longer owned by the caller after this.
  // May throw.
  void bar (struct foo *p);

  void some_function ()
  {
    struct foo *ptr = function_returning_new_ptr ();
    cleanup_pointer<struct foo *> cleanup (ptr);

    ptr->foo = .....;
    bar (ptr); // whoops, bar now owns the pointer, but
               // cleanup_pointer will delete it anyway
               // once we leave this scope
  
    // would need to remember to call this.
    // cleanup.discard ();
  }

That looks very much like our current cleanups, except we
no longer need the "do_cleanups" call.  But it's far from idiomatic
C++.   And, ends up being more code to write/maintain
than using a smart pointer.  We can do better.  E.g.,:

  // (gdb::unique_ptr is like std::unique_ptr and
  // gdb::move is like std::move for gdb::unique_ptr)

  // prototype clearly tells you this returns a new object.
  gdb::unique_ptr <struct foo> function_returning_new_ptr ();

  // Uses P, ownership is still with the caller.
  void foo (struct foo *p);

  // Clearly tells you this transfers ownership.
  void bar (gdb::unique_ptr <struct foo> p);

  void some_function ()
  {
    // struct foo *ptr = function_returning_new_ptr (); // would not compile.
    gdb::unique_ptr <struct foo> ptr
       = function_returning_new_ptr (); // OK, ownership clearly transferred to caller.

    ptr->foo = .....;
    foo (ptr.get ()); // clearly foo borrows the pointer.

    bar (gdb::move (ptr)); // clearly transfers ownership.
  }

The other use case a smart pointer clarifies is making
a structure/class be the owner of some pointer.  Like:

 struct foo
 {
   gdb::unique_ptr <struct foo> ptr;
 };

When a "foo" is destroyed, then ptr is destroyed automatically
as well.  Without the smart pointer, we'd have to explicitly
write delete ptr in a destructor:

 struct foo
 {
   ~foo() { delete ptr; }
   struct foo *ptr;
 };


Most C++03 projects past a size/history will bake their own
custom smart pointers for the use cases above.  Most large projects
will have invented theirs before std::unique_ptr existed though, so
they'll differ in API details.   However in our case, std::unique_ptr is
already there, so I think it makes a lot of sense to reuse the same
API, and take advantage of newer compilers as "lints", since
that's what people will be using for development anyway.  Once we do
require C++11, then we won't have to relearn a new smart pointer API.


Even if we were to use std::auto_ptr only, I would still think that that
would be an improvement over raw pointers, since with raw pointers
it's even easier to confuse "borrowing pointers" from "owning pointers",
since you have 0 zero help from the type system.  

The potential problems with std::auto_ptr stem from its
"move semantics", and are of the form:

  std::auto_ptr<type> ptr = function_returning_type ();

  std::auto_ptr<type> ptr2 = ptr;  // this moves instead of
                                   // copying.  I.e., ptr is NULL after this.

and:

  void function (std::auto_ptr<type> ptr);
  function (ptr);  // This moves instead of copying.  ptr is NULL after this.
  ptr->foo = 1; // crash.

In the latter case, the function prototype indicates that the caller
wants to transfer ownership of the pointer to the callee.  But that's
not clear at the call site.

So in C++03 mode, gdb::unique_ptr "allows" that too.  I.e., the compiler
won't complain.  However, that _won't_ compile in C++11 mode, forcing you
to write instead:

  gdb::unique_ptr<type> ptr2 = gdb::move (ptr);  // OK, now move is clearly
                                                 // what was intended.
  function (gdb::move (ptr2));  // Likewise.
  ptr2->foo = 1; // crash, but, obviously incorrect.

And of course the C++03 gdb::unique_ptr version supports this as well.

There's also the advantage that gdb::unique_ptr works with malloced
objects, and arrays (for 'new some_type[];').  We'd need _some_ smart
pointer for those, so std::auto_ptr alone won't be sufficient anyway...

WDYT?

Thanks,
Pedro Alves


  reply	other threads:[~2016-10-11 10:23 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-10 16:46 [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves
2016-10-10 16:46 ` [PATCH 3/3] 'struct parse_expression *' -> gdb::unique_ptr<expression> Pedro Alves
2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves
2016-10-10 17:49   ` Simon Marchi
2016-10-10 18:03     ` Pedro Alves
2016-10-11  6:48   ` Metzger, Markus T
2016-10-11 10:23     ` Pedro Alves [this message]
2016-10-11 10:53       ` Andreas Schwab
2016-10-11 11:17       ` Metzger, Markus T
2016-10-11 11:43         ` Pedro Alves
2016-10-11 13:58           ` Yao Qi
2016-10-11 14:05           ` Trevor Saunders
2016-10-11 12:16       ` Joel Brobecker
2016-10-11 13:46         ` Pedro Alves
2016-10-11 14:47           ` Joel Brobecker
2016-10-11 15:17             ` Eli Zaretskii
2016-10-11 16:24               ` Pedro Alves
2016-10-11 16:58                 ` Eli Zaretskii
2016-10-11 17:41                   ` Pedro Alves
2016-10-11 18:37                     ` Eli Zaretskii
2016-10-11 19:19                       ` Pedro Alves
2016-10-11 20:47                         ` Eli Zaretskii
2016-10-11 21:32                           ` Pedro Alves
2016-10-12  6:34                             ` Eli Zaretskii
2016-10-12  8:11                               ` Metzger, Markus T
2016-10-12  9:31                                 ` Eli Zaretskii
2016-10-12 10:12                                   ` Pedro Alves
2016-10-12 11:05                                     ` Eli Zaretskii
2016-10-12 11:25                                       ` Pedro Alves
2016-10-12 11:45                                         ` Eli Zaretskii
2016-10-13 12:12                                           ` Pedro Alves
2016-10-12 10:28                                 ` Pedro Alves
2016-10-12 11:07                                   ` Eli Zaretskii
2016-10-12 11:19                                     ` Pedro Alves
2016-10-12 11:41                                       ` Eli Zaretskii
2016-10-12 11:55                                         ` Pedro Alves
2016-10-13  0:38                                   ` [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) Pedro Alves
2016-10-13  0:45                                     ` [PATCH 2/2] gdb: Enable C++11 if available Pedro Alves
2016-10-13  0:45                                     ` [PATCH 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive Pedro Alves
2016-10-12  9:37                               ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves
2016-10-12 10:51                                 ` Eli Zaretskii
2016-10-12 11:15                                   ` Pedro Alves
2016-10-12 11:40                                     ` Eli Zaretskii
2016-10-12 11:45                                   ` Jan Kratochvil
2016-10-12 11:56                                     ` Luis Machado
2016-10-12 12:03                                     ` Eli Zaretskii
2016-10-13  9:07                                       ` Jan Kratochvil
2016-10-13 10:07                                         ` Eli Zaretskii
2016-10-13 10:27                                           ` Pedro Alves
2016-10-13 13:22                                             ` Eli Zaretskii
2016-10-13 13:36                                               ` Pedro Alves
2016-10-13 13:59                                                 ` Eli Zaretskii
2016-10-13 14:04                                                   ` Pedro Alves
2016-10-13 15:06                                                     ` Joel Brobecker
2016-10-13 10:46                                           ` Jan Kratochvil
2016-10-13 11:15                                             ` Pedro Alves
2016-10-13 13:28                                             ` Eli Zaretskii
2016-10-13 13:42                                               ` Pedro Alves
2016-10-13 14:07                                                 ` Eli Zaretskii
2016-10-11 19:23                       ` Simon Marchi
2016-10-11 20:54                         ` Eli Zaretskii
2016-10-11 21:28                           ` Simon Marchi
2016-10-12  6:23                             ` Eli Zaretskii
2016-10-11 21:16                         ` Jan Kratochvil
2016-10-11 17:15                 ` Luis Machado
2016-10-11 18:21                   ` Pedro Alves
2016-10-10 16:58 ` [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves
2016-10-16  7:05   ` Tom Tromey
2016-10-17 13:57     ` Pedro Alves
2016-10-17 14:07       ` Tom Tromey
2016-10-17 14:59         ` Pedro Alves
2016-10-20 13:46   ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ac1fe3e9-069c-a26e-e790-438b6ff3d3e9@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=markus.t.metzger@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox