mardi 2 juillet 2019

"Move or throw" using the ternary operator

Since C++11 I have been using the ternary operator to move or throw based on some condition, but with latest GCC (9.1 and trunk) is not working anymore.

I have reduced the problem to this example (Wandbox permalink):

#include <iostream>
#include <memory>

int main() 
{
    auto p = std::make_unique<int>();
    std::cout << "p.get(): " << p.get() << std::endl;

    {
        std::cout << "Move p into q" << std::endl;
        auto q = p ? std::move(p) : throw std::invalid_argument{"null ptr"};

        std::cout << "q.get(): " << q.get() << std::endl;
    }

    std::cout << "p.get(): " << p.get() << std::endl;
    return 0;
}

It works with GCC 8.3 and older, and with every Clang version; and p is moved:

p.get(): 0xde5c20
Move p into q
q.get(): 0xde5c20
p.get(): 0

But now with GCC 9.1 and later it doesn't work:

p.get(): 0x1d89150
Move p into q
q.get(): 0x1d89150
p.get(): 0x1d89150

And then the program crashes due to a double free.

Is this a bug in GCC 9.1/trunk? Or latest GCC is the only one doing the right thing and this is not valid C++?

Aucun commentaire:

Enregistrer un commentaire