c++ - 在嵌套的 lambda 中按值捕获指针会导致段错误

标签 c++ pointers lambda

首先,这是我遇到过的最晦涩的问题,因此也是最难问的问题。我将尝试通过发布最少的代码并提供一些上下文来尽可能清楚地说明这个问题。首先是出现问题的代码:

// Before lambda, pointer variable in question is fine
menu->onSelect = [=] ()
{
    window->pushCallback('e', [=]()
    {
        // Here the pointer captured changes, causing a segfault later on
    }
};

所以现在对于一些上下文:

pushCallback 的签名如下所示:

void Window::pushCallback(int key, std::function<void()> callback) {}

它存储一个函数,当调用第一个参数表示的键代码时要调用,在本例中为“e”。

Menu::onSelect 也是一个 std::function,存储单个函数以在选择菜单项时执行。

现在这个问题的模糊之处在于指针仅在第二次单步执行代码时发生变化。请注意,这是一个交互式 ncurses 程序。然而,我做了很多测试,发现两个显示的注释行之间的指针发生了变化。通过捕获嵌套 lambda 中的变量来显示突变发生。我还在所有引用它的类中将指针设为 const。

最佳答案

您不能像这样在嵌套的 lambda 中使用自动成员捕获,因为在执行外部 lambda 之前不会执行内部 lambda 的捕获。我相信 pre-C++ 之间存在一些差异14 和 C++14/17 但我不记得副手。我会调查并更新我的答案。

此外,我依稀记得在 G++ 和 Clang 之间遇到过一些差异,但这与编译器的提示有关,而不是与会导致段错误的实现差异有关。再次提醒,我会在记起来时更新。


变通,显式捕获变量或将其保存在 tmp 变量中。

std::shared_ptr<int> ptr; // This assumes that you are talking about shared pointers since I don't think you would have this problem with raw pointers unless the object is being destroyed before your lambda is being invoked
auto x = [ptr]()
     {
         // You could also create a temporary variable here to avoid ambiguity
         // std::shared_ptr<int> ptr2;
         return [ptr]() { return ptr; };
     };

我证实了我最初的假设是错误的。在这种情况下,共享点可以正常工作(但请确保您没有通过引用或所有赌注都关闭)。

auto foo(std::shared_ptr<int> p)
{
    return [=](int x) { return [=](int y) { return *p + x + y; }; };
}

int main()
{
    auto p = std::make_shared<int>(42);

    auto func = foo(p);

    std::cout << func(1)(2) << std::endl;

    ++(*p);

    std::cout << func(1)(2) << std::endl;

    return 0;
}

我建议查看 gdb 中的错误,如果您担心它正在被更改,可以在指针上设置硬件中断。

关于c++ - 在嵌套的 lambda 中按值捕获指针会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49633776/

相关文章:

c# - 在不使用iF字的情况下,根据 bool 结果触发函数

c++ - 从捕获的值变量分配给 Lambda 参数时出现 gcc 编译器段错误

c++ - GCC 编译器警告溢出

char *str[ ] 通过引用传递不起作用

c++ - 写入 int 与 uint16_t 时的内存填充

java - 在 JUnit 测试(java)中如何使用 Assertj 库检查数组的数组?

c++ - If 语句即使在不为真时也运行

c++ - 找不到体系结构 x86_64 的符号(带有 xcode 的 OpenGL)

c++ - 在 SWIFT 中使用 C++ FFT 代码

c - 为什么 argv 可以使用自增运算符