【问题标题】:I can't reproduce the function memoization from Functional Programming in C++我无法从 C++ 中的函数式编程中重现函数记忆
【发布时间】:2020-09-12 17:50:46
【问题描述】:

以下代码应该几乎是C++中的函数式编程一书在第 6 章第 1 节末尾介绍的内容的副本:

#include <iostream>
#include <utility>
#include <mutex>

template<typename F>
class lazy_val {
  private:
    F m_computation;
    mutable decltype(m_computation()) m_cache;
    mutable std::once_flag m_value_flag;
  public:
    lazy_val(F f)
        : m_computation(f)
    {}
    operator const decltype(m_computation())& () const {
        std::call_once(m_value_flag, [this](){
            m_cache = m_computation();
        });
        return m_cache; // the execution never gets to this line
    }
};

int expensive() {
    std::cout << "expensive call...\n";
    return 7;
}

int main() {
    std::cout << "non memoized" << '\n';
    std::cout << expensive() << '\n';
    std::cout << expensive() << '\n';
    std::cout << expensive() << '\n';
    const auto expensive_memo = lazy_val(expensive);
    std::cout << "memoized" << '\n';
    std::cout << expensive_memo << '\n'; // crash happens here
    std::cout << expensive_memo << '\n';
    std::cout << expensive_memo << '\n';
}

但是,当我执行它时(编译正常),我得到了这个错误:

non memoized
expensive call...
7
expensive call...
7
expensive call...
7
memoized
terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

如果忽略并发问题,只依赖初始化为falsemutable bool m_cache_initialized;if (!m_cache_initialized) { m_cache = m_computation(); m_cache_initialized = true; },那么一切正常。

这让我觉得问题在于我如何在代码中使用std::call_once/std::once_flag。但是我看不出它与书中显示的有什么不同(清单 6.2 中的构造函数,但没有将 m_cache_initialized 初始化为 false 的行,并且该类的其余部分位于第 125 页的底部和 126 的顶部)。

【问题讨论】:

    标签: c++ multithreading gcc runtime-error std-call-once


    【解决方案1】:

    您必须使用 Linux 和 gcc。此实现的一个“未记录”特性是,任何使用任何线程相关内容的 C++ 代码都必须与 -lpthread 显式链接。

    在编译(使用-std=c++17)并在没有-lpthread 的情况下链接之后,我在Linux 上重现了您的确切崩溃。如果与-lpthread 显式链接,则显示的代码运行良好。

    【讨论】:

    • 什么鬼!谢谢,我自己永远找不到这个! :) 我希望这对其他人有用。我会添加一些标签,以便更容易找到。
    猜你喜欢
    • 2011-08-10
    • 2016-07-15
    • 2022-12-17
    • 2021-03-30
    • 1970-01-01
    • 2012-11-26
    • 2021-12-22
    • 2014-06-02
    • 2013-05-30
    相关资源
    最近更新 更多