简体   繁体   English

在lambda中捕获std :: function对象

[英]Capturing std::function objects in lambda

Below code fails with BAD_ACCESS when I call s_capture_void_int() in the last line and I do not understand why. 当我在最后一行调用s_capture_void_int()并且我不明白为什么时,下面的代码在BAD_ACCESS失败。 I suppose that when I assign lambda expression to a global variable it supposed to copy itself together with captured values. 我想当我将lambda表达式赋给全局变量时,它应该将自己与捕获的值一起复制。 So in my understanding dangling references should not appear. 所以在我的理解中,不应出现悬挂引用。 But it looks like I'm missing something. 但看起来我错过了一些东西。

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
}

I don't understand two things here: 我不明白这里有两件事:

  • If crash happen because of func3_fn goes out of scope then why case 1 and 2 works? 如果由于func3_fn超出范围而发生崩溃,那么为什么案例1和2有效?
  • If I change this code to std::function (note no parameter) then it works ok. 如果我将此代码更改为std :: function(注意没有参数),那么它可以正常工作。 Could it be a compiler bug? 它可能是编译器错误吗?

I'd say it's a compiler bug. 我会说这是编译器错误。 It works fine in GCC . 在GCC中运行良好 Perhaps the param in capture_void_int is incorrectly captured by reference (since it's a reference) when it should instead be captured by value. 也许capture_void_intparam被引用错误地捕获(因为它是一个引用),而它应该被值捕获。

For anybody who come across same problem. 对于任何遇到同样问题的人。 This is indeed a compiler bug and I found simple and stupid workaround. 这确实是一个编译器错误,我找到了简单而愚蠢的解决方法。 Workaround is not tested but at least my program does not segfault right away on a first call to std::function. 解决方法未经过测试,但至少我的程序在第一次调用std :: function时不会立即发生段错误。 Problem manifest itself with clang shipped with Xcode 5.0.2 and 5.1 compiler. 使用Xcode 5.0.2和5.1编译器附带的clang出现问题。 gcc 4.8 and possibly stock clang does not have this problem. gcc 4.8和可能的股票clang没有这个问题。 Simplest possible program to trigger problem: 最简单的触发问题的程序:

#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;
}

If you uncomment 'workaround' function it magically start working. 如果您取消注释“变通方法”功能,它会神奇地开始工作。 Order of functions is important, workaround function have to be before any other functions using std::function. 函数顺序很重要,解决方法函数必须在使用std :: function之前的任何其他函数之前。 If you put 'workaround' below 'trigger_bug' then it stop working. 如果你将'workaround'放在'trigger_bug'下面,那么它就会停止工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM