众所周知,返回指向堆栈变量的指针通常是不明智的:
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
实现中的错误还是以这种方式返回指针是基本不正确的(类似于第一个示例)。
Generator
实现为例,我并没有看到任何问题。虽然它缓存了产生的值,但协程只有在调用operator bool
并且将要返回false
时才会进入最终暂停点(其中b
的生命周期结束),这对应于 range-for 中的最终条件测试,应该在循环体的最后一次迭代之后才进行评估。所以我认为你的generator
实现是有问题的。(co_return
将是不同的) - user17732522