当我在最后一行调用s_capture_void_int()时,代码在BAD_ACCESS失败,我不明白为什么。我想当我将lambda表达式赋给全局变量时,它应该将自己与捕获的值一起复制。所以在我的理解中,不应出现悬挂引用。但看起来我错过了什么。
std::function<void()> s_capture_void_int;
void capture_void_int (const std::function<void(int)>& param)
{
s_capture_void_int = [param]() {
param(1);
};
}
void capture_local_lambda()
{
auto local_lambda = [](int) {
};
s_capture_void_int = [local_lambda]() {
local_lambda(1);
};
}
BOOST_AUTO_TEST_CASE( test_lambda_captures )
{
//Case 1: this works
auto func2 = [](int){};
{
std::function<void(int)> func2_fn(func2);
s_capture_void_int = [func2_fn]() { func2_fn(1); };
}
s_capture_void_int();
//case 2: even this works.
capture_local_lambda();
s_capture_void_int();
//case 3: but this fails.
auto func3 = [](int){};
{
std::function<void(int)> func3_fn(func3);
capture_void_int(func3_fn);
}
s_capture_void_int(); //<- it crashes here
}
我不明白这里有两件事:
答案 0 :(得分:1)
我说这是编译错误。它works fine in GCC。也许param
中的capture_void_int
被引用错误地捕获(因为它是引用),而应该通过值捕获它。
答案 1 :(得分:1)
对于遇到同样问题的人。这确实是一个编译器错误,我找到了简单而愚蠢的解决方法。解决方法未经过测试,但至少我的程序在第一次调用std :: function时不会立即发生段错误。 使用Xcode 5.0.2和5.1编译器附带的clang出现问题。 gcc 4.8和可能的股票clang没有这个问题。最简单的程序来触发问题:
#include <iostream>
#include <functional>
std::function<void()> buggy_function;
/*
void workaround (const std::function<void(int)>& param)
{
auto a = [&,param]() {
param(1);
};
}
*/
void trigger_bug (const std::function<void(int)>& param)
{
buggy_function = [&,param]() {
param(1);
};
}
int main(int argc, const char * argv[])
{
auto func3 = [](int){};
std::function<void(int)> func3_fn(func3);
trigger_bug(func3_fn);
buggy_function();
return 0;
}
如果您取消注释&#39;解决方法&#39;它神奇地开始工作。函数顺序很重要,解决方法函数必须在使用std :: function之前的任何其他函数之前。如果你把'解决方法'&#39;在下面&#39; trigger_bug&#39;然后它停止工作。