user118534
user118534

Reputation: 101

Is it unsafe to co_yield a pointer to a local coroutine variable?

It's common knowledge that returning a pointer to a stack variable is generally a bad idea:

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

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

In the example above, my understanding is that the int is destroyed and so p is a dangling pointer.

I am wondering about the extent to which this applies to the newly introduced coroutines of 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)) {
    /* ... */
  }
}

In this example, the coroutine read yields a span view into the local buffer b. Internally, that view stores a pointer to the buffer. Will that pointer ever be dangling when v is used with the body of the range-for loop?

For context, the coroutine code in the second example is modeled after the code in my own project. There, AddressSanitizer ends the program with a "use-after-free" error. Ordinarily I'd consider that enough to answer my question, but since coroutine development is still coming along at this point in time (my project is using boost::asio::experimental::coro, emphasis on "experimental"), I was wondering if the error was caused by a bug with generator's implementation or if returning pointers in this way is fundamentally incorrect (similar to the first example).

Upvotes: 10

Views: 327

Answers (1)

Davis Herring
Davis Herring

Reputation: 40013

With language coroutines, this has to be safe: the lifetime of b must continue until the generator is finished, so pointers to it must be useful that long.

Upvotes: 2

Related Questions