在调用该函数期间释放包含 std::function 的可选内容

问题描述 投票:0回答:1

我有一个问题,但我似乎无法在标准中找到明确的答案。我想知道我在这里所做的事情是否定义明确(因此可以信赖)

我有一个代表线程的类,并且在该类中有一个成员

std::optional<std::function<void()>> ops;

每隔一段时间,当线程不忙于执行其他代码时,它会检查

ops
是否有值,如果有,则会执行它。 (适当锁定)。

我想知道的是:从当前加载到

ops.clear()
的函数中调用
ops
是否是明确定义的行为。

这是一个更具说明性的示例,没有线程但仍保持锁定:

class ops_t
{
  private:
    std::mutex mutex;
    std::optional<std::function<void()>> ops;
  public:
    void set_ops(std::function<void()> new_ops)
    {
      std::lock_guard guard(mutex);
      ops = new_ops;
    }

    void clear_ops()
    {
      std::lock_guard guard(mutex);
      ops.reset();
    }

    void do_ops()
    {
      std::optional<std::function<void()>> ops_local = [this]() // make copy so we don't hold mutex while executing
      {
        std::lock_guard guard(mutex);
        return ops;
      }();
      if(ops_local)
        (*ops_local)();
    }
};


int main(void)
{
  ops_t ops;
  ops.set_ops(std::bind_front(&ops_t::clear_ops, &ops));
  ops.do_ops(); // is the sequence of events triggered here well defined by the standard?
}

发布在通话期间自毁std::function并没有回答我的问题。那里接受的答案与指向被删除对象的指针有很大的分歧;不过我没有这个问题。

编译此代码有效并运行它不会导致分段错误;然而这种情况相当奇怪,因此我试图确认它是由 c++20 标准很好定义的

c++ runtime-error c++20
1个回答
0
投票

您的代码没有按照您的想法进行操作。

您的代码创建 std 函数的堆栈本地副本,然后运行它。运行它时,它会保存 fubction 对象的类副本(在选项中)。

这两个对象是不相关的(嗯,一个是另一个的副本),因此不存在生命周期问题。

所以您发布的代码是安全的。

如果您确实按照其余问题的要求进行操作,我相信您的代码将超出 tge 标准定义行为的范围。

我上次检查过,std 函数不保证它在其拥有的

operator()
运行后不会触及自己的状态。也许可以做出这样的保证,但措辞会很尴尬。

因此,大多数(但不是全部)std 函数实现将继续存在 if 触及函数对象状态的最后一个操作会破坏 std 函数,但您的代码仍会被视为存在 UB,因为它位于已破坏的 std 对象的方法中。

© www.soinside.com 2019 - 2024. All rights reserved.