Lig*_*ica 7 c++ gcc shared-ptr libstdc++ default-arguments
看看这个:
#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?)
Run Code Online (Sandbox Code Playgroud)
我希望shared_ptr在bar()返回时调用删除器,在使用GCC 4.8.5的64位CentOS 7系统上调用它.
然而,在我的32位的CentOS下devtoolset 2中使用GCC 4.8.2 6系统(我也想下gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux,我的树莓派工具链),它没有.
看一下代码,并给出了4.8中C++ 11的实验性质,这对我来说就像一个编译器错误.但我也可能陷入某个地方的UB陷阱(或者只是误解了这些东西应该如何工作).
谁有过错?我该如何解决?
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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
应该在bar返回时调用析构函数,或者调用完整表达式的结尾bar.
如果我们看一下[expr.call]/4(C++ 17草案)
当一个函数被调用时,每个参数(11.3.5)应该用它对应的参数进行初始化(11.6,15.8,15.1).[...]实现定义一个参数的生命周期是否在函数中结束它是定义的回报或在封闭的完整表达的末尾.[...]
所以p应该在函数FooPtr开始时初始化为null ,移动分配返回MakeFoo,然后bar在bar返回结束时或之后最终销毁(反过来调用删除器)main.
正如内森(Nathan)所表明的,我对指针生命周期的假设是标准正确的。
删除器没有被调用确实似乎是一个 GCC 或 libstdc++ 错误,考虑到链接的注释解决了它,可能是错误 60367 ,症状似乎相似,并且在 GCC 4.8.5 之前已修复。
替换= {}为= FooPtr{}似乎是一个可行的解决方法。
请注意,7.2 和一些较旧的“8.0”主干构建中也存在回归,可能会在类似情况下导致不良行为(感谢Arne Vogel!)。
| 归档时间: |
|
| 查看次数: |
352 次 |
| 最近记录: |