c++ - clang - shared_ptr 无法运行其删除程序
问题描述
当使用(yield ,这是我所期望的)构建时,此代码会打印0
(没有优化)或666
(打开优化)。当 lambda 通过通用引用传递时,问题就消失了。clang++ -std=c++11
-O3
666
仅供参考,GCC 打印666
在我测试过的所有版本上。
是编译器错误还是代码不正确?
#include <memory>
#include <iostream>
template <typename T>
std::shared_ptr<void> onScopeExit(T f)
{
return std::shared_ptr<void>((void*)1, [&](void *) {
f();
});
}
struct A {
void f() {
auto scopeGuard = onScopeExit([&]() { i = 666; }); // [1]
// ... (some work)
} // (lambda [1] being ? called on scope exit)
int i = 0;
};
A a;
int main() {
a.f();
std::cout << a.i << std::endl;
}
有问题的编译器是:
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
解决方案
您的代码具有未定义的行为。f
您通过引用捕获,onScopeExit
但是一旦您shared_ptr
从函数返回,删除器现在持有对 的悬空引用f
,因为f
超出了范围。您需要做的是f
按价值捕获,然后您就不会有悬空引用
template <typename T>
std::shared_ptr<void> onScopeExit(T f)
{
return std::shared_ptr<void>((void*)1, [=](void *) {
f();
});
}
struct A {
void f() {
auto scopeGuard = onScopeExit([&]() { i = 666; }); // [1]
// ... (some work)
} // (lambda [1] being ? called on scope exit)
int i = 0;
};
A a;
int main() {
a.f();
std::cout << a.i << std::endl;
}
推荐阅读
- haskell - 从控制台读取 INT 类型的列表,并仅打印给定列表中的偶数使用列表推导
- java - 如何在片段中添加后退箭头以进行后退操作?
- javascript - 如何触发视图中数据的更新?
- haskell - 使用列表推导生成元组
- php - ErrorException:imagecreatefromstring():gd-jpeg,libjpeg:可恢复错误:顺序 JPEG 的 SOS 参数无效
- arduino - 用于 Mega 的 ENC28J60 SS 引脚
- c++ - 了解 nth_element
- python - A-star 比 dijkstra 慢
- swift4 - EXC_BAD_INSTRUCTION code=EXC_I386_INVOP 斐波那契计数函数
- dart - 如何仅在显示页面时激活位置侦听器?