Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Have I misunderstood the scope of this default argument shared_ptr?

Take a look at this:

#include <iostream>
#include <memory>

using Foo = int;
using FooPtr = std::shared_ptr<Foo>;

FooPtr makeFoo()
{
    FooPtr f{
        new Foo(),
        [](Foo* ptr) {
            delete ptr;

            std::cerr << "!\n";
        }
    };

    return f;
}

void bar(FooPtr p = {})
{
    p = makeFoo();
}

int main()
{
    bar();
}

// Expected output: '!'
// Failure case: no output (deleter not invoked?)

I expected the shared_ptr deleter to be called when bar() returns, and on my 64-bit CentOS 7 system using GCC 4.8.5, it does.

However, on my 32-bit CentOS 6 system using GCC 4.8.2 under devtoolset-2 (also I think under gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux, my Raspberry Pi toolchain), it doesn't.

Looking at the code, and given C++11's experimental nature in 4.8, this smells like a compiler bug to me. But I could also be falling into a UB trap somewhere (or just generally misunderstanding how this stuff ought to work).

Who's at fault? And how should I fix it?


Works on

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)

Fails on

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-2/root/usr/libexec/gcc/i686-redhat-linux/4.8.2/lto-wrapper
Target: i686-redhat-linux
Configured with: ../configure --prefix=/opt/rh/devtoolset-2/root/usr --mandir=/opt/rh/devtoolset-2/root/usr/share/man --infodir=/opt/rh/devtoolset-2/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,fortran,lto --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-i686-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-i686-redhat-linux/cloog-install --with-mpc=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-i686-redhat-linux/mpc-install --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
Thread model: posix
gcc version 4.8.2 20140120 (Red Hat 4.8.2-15) (GCC)
like image 728
Lightness Races in Orbit Avatar asked Mar 26 '18 18:03

Lightness Races in Orbit


1 Answers

The destructor should be called either when bar returns or and the end of the full expression in which bar is called.

If we look at [expr.call]/4 (C++17 draft) we have

When a function is called, each parameter (11.3.5) shall be initialized (11.6, 15.8, 15.1) with its corresponding argument.[...]It is implementation-defined whether the lifetime of a parameter ends when the function in which it is defined returns or at the end of the enclosing full-expression.[...]

So p should be initialized to a null FooPtr at the start of the function, move assigned the return of MakeFoo, and then finally destroyed (in turn calling the deleter) at the end of bar or after bar returns in main.

like image 144
NathanOliver Avatar answered Sep 26 '22 13:09

NathanOliver