将局部协程变量的指针co_yield出去是否安全?

10

众所周知,返回指向堆栈变量的指针通常是不明智的:

int* foo() {
  int i = 0;
  return &i;
}

int main() {
  int* p = foo();
}

以上示例中,我的理解是int被销毁了,因此p成为了悬空指针。

我想知道这是否也适用于C++20中新引入的协程:

generator<span<byte>> read(stream& s) {
  array<byte, 4096> b;
  while (s.is_open()) {
    const size_t n = s.read_some(b);
    co_yield span(b, n);
  }
}

int main() {
  stream s;
  for (span<byte> v : read(s)) {
    /* ... */
  }
}
在这个例子中,协程read产生了一个对本地缓冲区b视图。在内部,该视图存储了指向缓冲区的指针。当与range-for循环体一起使用时,v是否会出现悬空指针的情况?
为了背景上下文,第二个示例中的协程代码是根据我的自己的项目中的代码建模而来的。在那里,地址无害化器用“use-after-free”错误结束程序。通常我会考虑这足以回答我的问题,但由于协程开发仍在进行中(我的项目正在使用boost::asio::experimental::coro,强调“实验性”),我想知道错误是由于generator实现中的错误还是以这种方式返回指针是基本不正确的(类似于第一个示例)。

如果以 https://en.cppreference.com/w/cpp/language/coroutines 上的 Generator 实现为例,我并没有看到任何问题。虽然它缓存了产生的值,但协程只有在调用 operator bool 并且将要返回 false 时才会进入最终暂停点(其中 b 的生命周期结束),这对应于 range-for 中的最终条件测试,应该在循环体的最后一次迭代之后才进行评估。所以我认为你的 generator 实现是有问题的。(co_return 将是不同的) - user17732522
1个回答

2

使用语言协程,这必须是安全的: b生命周期必须持续到生成器完成,因此指向它的指针必须在此期间保持有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接