我是否误解了此默认参数shared_ptr的范围? [英] Have I misunderstood the scope of this default argument shared_ptr?

查看:98
本文介绍了我是否误解了此默认参数shared_ptr的范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看看这个:

  #include< iostream> 
#include< memory>

使用Foo = int;
使用FooPtr = std :: shared_ptr< Foo> ;;

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

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

返回f;
}

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

int main()
{
bar();
}

//预期输出:!
//失败案例:无输出(未调用deleter?)

我希望在 bar()时调用 shared_ptr 删除程序返回,并在使用GCC 4.8.5的64位CentOS 7系统上返回。



但是,在我的32位CentOS 6系统上在devtoolset-2下使用GCC 4.8.2(我也在 gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux 下的 think



看看代码,考虑到C ++ 11在4.8中的实验性质,这对我来说就像是编译器错误。但是我也可能会陷入某个地方的UB陷阱(或者只是一般地误解了这些东西应该如何工作)。



谁在过错?我应该如何解决?








<$ p上工作$ p> 使用内置规格。
COLLECT_GCC = g ++
COLLECT_LTO_WRAPPER = / usr / libexec / gcc / x86_64-redhat-linux / 4.8.5 / lto-wrapper
目标:x86_64-redhat-linux
配置:../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
线程模型:posix
gcc版本4.8.5 20150623(Red Hat 4.8.5-16)(GCC )



失败



 使用内置规格。 
COLLECT_GCC = g ++
COLLECT_LTO_WRAPPER = / opt / rh / devtoolset-2 / root / usr / libexec / gcc / i686-redhat-linux / 4.8.2 / lto-wrapper
目标:i686 -redhat-linux
配置为:../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-安装--with-mpc = / builddir / build / BUILD / gcc-4.8.2-20140120 / obj-i686-redhat-linux / mpc-install --with-tune = generic --with-a rch = i686 --build = i686-redhat-linux
线程模型:posix
gcc版本4.8.2 20140120(Red Hat 4.8.2-15)(GCC)


解决方案

如Nathan所示,我对指针寿命的假设是标准正确的。



未调用删除程序似乎是GCC或libstdc ++错误,可能是错误60367 鉴于链接的注释解决了该问题,其症状似乎相似,并且已在GCC 4.8.5之前修复。



= FooPtr {} 替换 = {} 似乎是一个可行的解决方法。






请注意,还有在7.2和一些较旧的 8.0主干构建中的回归可能在类似情况下导致不良行为(感谢 Arne Vogel !)。


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)

解决方案

As Nathan has shown, my assumptions about the pointer's lifetime were standard-correct.

That the deleter isn't being invoked does appear to be a GCC or libstdc++ bug, possibly bug 60367 given that the linked comment solves it, the symptoms seem similarish and it was fixed before GCC 4.8.5.

Replacing = {} with = FooPtr{} appears to be a viable workaround.


Note well, there is also a regression in 7.2 and some older "8.0" trunk builds that may cause bad behaviour in similar circumstances (thanks Arne Vogel!).

这篇关于我是否误解了此默认参数shared_ptr的范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆