我是否误解了此默认参数shared_ptr的范围? [英] Have I misunderstood the scope of this default argument 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()时调用
返回,并在使用GCC 4.8.5的64位CentOS 7系统上返回。 shared_ptr
删除程序
但是,在我的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屋!