我最近在我们的代码库中发现了几个lambdas,它们大部分时间都在工作,但依赖于未定义的行为。这是一个例子:
#include <iostream>
#include <thread>
std::thread thread;
void foo(int bar)
{
thread = std::thread([&]() { std::cout << bar << std::endl; });
}
int main(int argc, char* argv[])
{
foo(5);
thread.join();
}
问题是具有局部范围(bar)的变量通过引用捕获并在以后访问。奇怪的是,我们的编译器(GCC,Clang,MSVC)都没有默认警告,即使它应该像#34;警告一样容易捕获:返回本地临时对象的地址&#34;。有没有办法让任何提到的编译器对此发出警告?
答案 0 :(得分:1)
最近这也引起了我的兴趣。我意识到我通过参考bloomin'到处来捕获函数args。
在这种情况下,我很想得到关于此事的警告,但我怀疑我们不这样做的原因是在很多情况下捕获没有任何问题。只要你立即执行lambda,你就安全了。只有在您将其存储以供以后使用时(包括在工作线程中),您才可能遇到问题。
要么编译器还不够聪明,要么他们的作者决定不对此发出警告。
无论如何,我都不知道任何主流编译器会对你的代码发出警告。所以你必须非常小心。
答案 1 :(得分:0)
您没有返回临时变量的地址。传递临时变量的引用很好。当然,当你通过引用传递变量时,如果源函数已经过期,那么它可能会导致意外的结果。
但是,编译器并不关心线程创建和线程顺序。因为人们可能会使用自己的线程库而不是std::thread
。从编译器的角度来看,它只是寻找语言结构的有效性,而[&](...){}
是一个有效的结构。
换句话说,编译器无法捕获此(实际上有用)警告。可悲的是,这是程序员的责任。您可以将argv
复制到std::string
对象并按值传递。