clang - shared_ptr 无法 运行 它的删除器
clang - shared_ptr fails to run its deleter
此代码在使用 clang++ -std=c++11
构建时打印 0
(没有优化)或 666
(打开优化)(-O3
产生 666
,这是我所期望的)。当通过通用引用传递 lambda 时,问题就消失了。
仅供参考,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
您的代码有未定义的行为。您通过 onScopeExit
中的引用捕获 f
,但是一旦您从函数中 return 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;
}
此代码在使用 clang++ -std=c++11
构建时打印 0
(没有优化)或 666
(打开优化)(-O3
产生 666
,这是我所期望的)。当通过通用引用传递 lambda 时,问题就消失了。
仅供参考,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
您的代码有未定义的行为。您通过 onScopeExit
中的引用捕获 f
,但是一旦您从函数中 return 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;
}