gpt4 book ai didi

c++ - 在移动的 lambda 中捕获和调试对局部变量引用的无效使用

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:36:55 25 4
gpt4 key购买 nike

在我的一个实际项目中,我遇到了一个难以调试的情况,我不小心访问了对已移动的 lambda 内部局部变量的引用。访问是从另一个线程完成的,但是移动的 lambda 一直保持事件状态,直到第二个线程完成。

该错误仅在禁用优化时出现,并且是由粗心的重构引起的。

我创建了一个最小示例 (available here on wandbox)重现问题:

struct state
{
int x = 100;
};

template <typename TF>
void eat1(TF&& f)
{
// Call the lambda.
f();

// Simulate waiting for the second thread
// to finish.
std::this_thread::sleep_for(1000ms);
}

template <typename TF>
void eat0(TF&& f)
{
// Move the lambda to some other handler.
eat1(std::forward<TF>(f));
}

void use_state(state& s)
{
// Will print `100`.
std::cout << s.x << "\n";

// Separate thread. Note that `s` is captured by
// reference.
std::thread t{[&s]
{
// Simulate computation delay.
std::this_thread::sleep_for(500ms);

// Will print garbage.
std::cout << s.x << "\n";
}};

t.detach();
}

int main()
{
eat0([]
{
// Local lambda variable that will be accessed
// after the lambda is moved.
state s;

// Function that takes `s` by reference and
// accesses it in a separate thread after the
// lambda is moved.
use_state(s);
});
}

令人惊讶的是,所有 sanitizer 和警告标志都没有起到帮助作用。

我尝试了以下编译器和 sanitizer 的组合,

-Wall -Wextra -Wpedantic -g -O0

标志始终启用:

  • 编译器:g++ 6.1.1 在 Arch Linux x64 上; clang++ 3.8.0 在 Arch Linux x64 上; g++ 5.3.1 在 Fedora x64 上; Fedora x64 上的 clang++ 3.7.0

  • sanitizer :-fsanitize=address-fsanitize=undefined-fsanitize=thread

没有一种组合产生任何有用的诊断。我希望 AddressSanitizer 告诉我我正在访问悬空引用,或者 UndefinedSanitizer 在访问它时捕获 UB,或者 ThreadSanitizer 告诉我一个单独的线程正在访问无效的内存位置。

是否有可靠的方法来诊断此问题?我是否应该将此示例作为功能请求/缺陷发布到任何 sanitizer 的错误跟踪器?

最佳答案

valgrind 的 memcheck 工具在默认设置下发现了这个问题。然而,这种讨厌的错误有机会逃脱 memcheck。我不确定问题是否会在实际程序中被发现。

第一个 lambda 被移动的事实与问题无关(尽管它可能使调试过程复杂化)。问题是由于访问已完成执行的函数中的局部变量(同样,从不同线程发生访问的事实只会使调查更加困难,但不会以任何其他方式导致错误)。第一个 lambda 保持事件状态的事实绝不应该保护您 - 局部变量属于 lambda 调用 而不是 lambda 本身。

关于c++ - 在移动的 lambda 中捕获和调试对局部变量引用的无效使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39307730/

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