gpt4 book ai didi

c++ - 当另一个调用 lambda 使用默认捕获时,lambda 的闭包会被破坏吗?

转载 作者:行者123 更新时间:2023-11-28 01:24:44 24 4
gpt4 key购买 nike

这似乎是一个编译器错误,但它同时出现在 gcc 和 clang(可能还有其他)中。

如果一个函数接受一个 lambda f 并且它从另一个调用 f 的 lambda g 创建一个线程,f 可以安静地失去对其捕获的变量的访问权限。这是一个演示。

#include <thread>
#include <iostream>

using std::cout;
using std::endl;
using std::thread;

template<typename F>
__attribute__((noinline)) // inlining hides the bug
thread* callMeLater1(F f)
{
return new thread(
[&]() {
// ...
// Insert sleep logic.
// ...

f();
});
}

template<typename F>
__attribute__((noinline))
thread* callMeLater2(F f)
{
return new thread(
[f]() {
// ...
// Insert sleep logic.
// ...

f();
});
}


int main(int argc, const char * argv[]) {
int a = 42;

cout << "orign: " << ((void*) &a) << endl;

auto f = [&]() {
cout << "later: " << ((void*) &a) << endl;
};

thread* t1 = callMeLater1(f);
t1->join();
delete t1;

thread* t2 = callMeLater2(f);
t2->join();
delete t2;

return 0;
}

这是结果。

orign: 0x7ffee88727ac
later: 0
later: 0x7ffee88727ac

callMeLater1 中对 f 的调用已损坏。 fa 的访问将被破坏,导致静默错误或段错误。当在 callMeLater2 中调用 f 时,它不使用默认捕获 &,该函数可以正常工作。

这是预期的吗?

最佳答案

这是未定义的行为。

lambda 通过引用捕获 callMeLater1 的参数。当然,一旦 callMeLater1 返回,这个参数就会被销毁。

没有任何东西可以保证新的执行线程会在 callmeLater1 返回之前调用传入的闭包。因此,传入的可调用对象可能会在新线程尝试调用它之前被销毁,从而导致未定义的行为。

关于c++ - 当另一个调用 lambda 使用默认捕获时,lambda 的闭包会被破坏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54374599/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com