public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "pinskia at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/115050] Segfault when compiled with -O0
Date: Tue, 28 May 2024 21:43:29 +0000	[thread overview]
Message-ID: <bug-115050-4-goxzeZzlfz@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-115050-4@http.gcc.gnu.org/bugzilla/>

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115050

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
There is a copy of Tester involved before F's constructor fully happens so we
call ~FBase (on the unwind) which then calls the bad (vtable) deconstructor.
Why it happens at -O0 only is just by accident. At -O1 we do some
de-virtualization which allows the (right) deconstructor to be called. Note
GCC's VTable::~VTable sets the vtable to be VTable's vtable which exposes the
bug. This only happens at -O0 because at -O1 and above it is considered a dead
store.

This is definitely undefined code without the following change because you
might get ~VTable being called twice.



Note if you change VTable to:
```
class VTable
{
  public:
        virtual void func(int x) = 0; // #1 this line affects behavior
        virtual ~VTable() {__builtin_printf("~vtable\n");}
};
```

You will see there is 2 calls to ~VTable which is incorrect.



Changing FBase/F to this:
```

struct FBase
{
        static constexpr int S = sizeof(void*) + sizeof(VTable);
        bool constructed = false;
        std::byte _data[S];

        ~FBase() { if (!constructed) return;
static_cast<VTable*>(static_cast<void*>(&_data[0]))->~VTable(); } // #2 this
line affects behavior
};

struct F : FBase
{
        template <typename T>
        F(T&& t) {
                static_assert(sizeof(Handler<std::decay_t<T>>) <= S);
                ::new (&_data[0]) Handler<std::decay_t<T>>(std::forward<T>(t));
                constructed = true;
        }

        ~F() = default;
};
```

Fixes the issue and only one call to ~VTable happens.

      parent reply	other threads:[~2024-05-28 21:43 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-12 11:40 [Bug c++/115050] New: " lobel.krivic at proton dot me
2024-05-12 11:44 ` [Bug c++/115050] " pinskia at gcc dot gnu.org
2024-05-12 15:50 ` sjames at gcc dot gnu.org
2024-05-28 21:43 ` pinskia at gcc dot gnu.org [this message]

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=bug-115050-4-goxzeZzlfz@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).