Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

c++ coroutine, done() function returns different value in a same loop

godbolt: https://godbolt.org/z/6avWcGqKv

The following code, compiled and run with g++ 12, 13, 14, all give the same (wrong?) output.

clang 18, 19 are fine (all "done: 1").

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is it my programming error, or compiler error, or some UB, or something?

Program returned: 0
done: 1
done: 1
done: 1
done: 1
done: 1
done: 0  <-- ???
done: 1
done: 1
done: 1
done: 1

code:

#include <coroutine>
#include <iostream>
#include <vector>

struct Task {
  struct promise_type {
    Task get_return_object() {
      return {.h = std::coroutine_handle<>::from_address(this)};
    }
    std::suspend_never initial_suspend() noexcept { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    void unhandled_exception() {}
    void return_void() {}
  };
  std::coroutine_handle<> h;
};

Task coro() { co_return; }

int main() {
  std::vector<Task> v;
  for (int i = 0; i < 10; ++i)
    v.push_back(coro());
  for (auto &t : v)
    std::cout << "done: "<< t.h.done() << "\n";

  return 0;
}

>Solution :

Per cppreference, std::coroutine_handle<Promise>::from_address can only be passed the result of another’s (compatible) handle std::coroutine_handle<Promise>::address but you are passing the address of promise_type. To reconstruct the handle from that, you need std::coroutine_handle<Promise>::from_promise

Task get_return_object() {
      return { std::coroutine_handle<promise_type>::from_promise(*this)};
    }

returns all ones with gcc https://godbolt.org/z/9E8aMdK1v

The original code compiled with clang and -fsanitize=memory complained about:

==1==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x55555561f462 in std::ostream::operator<<(bool) /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/ostream:183:16
    #1 0x55555561f462 in main /app/example.cpp:25:26
    #2 0x7ffff7829d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
    #3 0x7ffff7829e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
    #4 0x555555586324 in _start (/app/output.s+0x32324)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /app/example.cpp:25:26 in main
Exiting
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading