https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119916
Zartaj Majeed <zmajeed at sbcglobal dot net> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |zmajeed at sbcglobal dot net --- Comment #22 from Zartaj Majeed <zmajeed at sbcglobal dot net> --- Thank you for the quick fix. I ran into this bug recently with gcc 15.1 - didn't occur to me to check bugzilla right away - but was very happy to find it reported and fixed already! I verified the fix on master with this little program below - but I wonder if someone could explain an additional difference in behavior I'm seeing ---------------------------- // int_coroutine.cpp #include <coroutine> #include <print> using namespace std; struct Tag {}; struct IntRO { struct promise_type { int result = -999; auto get_return_object() noexcept { return IntRO{coroutine_handle<promise_type>::from_promise(*this)}; } suspend_never initial_suspend() noexcept { return {}; } suspend_always final_suspend() noexcept { return {}; } void return_value(int x) noexcept { result = x; } void unhandled_exception() noexcept { } }; operator int() { return coro.promise().result; } #if NO_CORO_CHECK ~IntRO() { coro.destroy(); } #else ~IntRO() { if(coro.done()) { coro.destroy(); } } #endif coroutine_handle<promise_type> coro; }; template<> struct std::coroutine_traits<int, Tag> { using promise_type = IntRO::promise_type; }; int main() { auto result = [](Tag) static -> int { co_return 13; }({}); println("main: int coroutine returned {}, expected 13", result); return result == 13? 0: 1; } ---------------------------- With installed GCC 15.1.1 g++ -dumpfullversion && g++ -std=c++26 -o int_coroutine.gcc15 int_coroutine.cpp && ./int_coroutine.gcc15 15.1.1 main: int coroutine returned -999, expected 13 With GCC built from master build/g++ -dumpfullversion && build/g++ -std=c++26 -o int_coroutine.gcc16 int_coroutine.cpp && ./int_coroutine.gcc16 16.0.0 IntRO.destructor: destroy own coro 0xa000165c0 main: int coroutine returned 13, expected 13 ---------------------------- The extra difference is when InRO destructor runs with GCC from master, coro.done() returns true and coro.destroy() succeeds But for GCC 15.1.1, coro.done() returns false and coro.destroy() is not called - indeed removing the check and calling coro.destroy() unconditionally causes a SIGABRT crash There is no crash with GCC from master when coro.destroy() is called unconditionally ---------------------------- g++-15 -dumpfullversion && g++-15 -std=c++26 -DNO_CORO_CHECK -o int_coroutine.nocheck.gcc15 int_coroutine.cpp && ./int_coroutine.nocheck.gcc15 15.1.1 free(): double free detected in tcache 2 Aborted (core dumped) Stack trace in gdb Program received signal SIGABRT, Aborted. __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44 #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x00007ffff784527e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x00007ffff78288ff in __GI_abort () at ./stdlib/abort.c:79 #5 0x00007ffff78297b6 in __libc_message_impl (fmt=fmt@entry=0x7ffff79ce8d7 "%s\n") at ../sysdeps/posix/libc_fatal.c:134 #6 0x00007ffff78a8ff5 in malloc_printerr (str=str@entry=0x7ffff79d1bf0 "free(): double free detected in tcache 2") at ./malloc/malloc.c:5772 #7 0x00007ffff78ab55f in _int_free (av=0x7ffff7a03ac0 <main_arena>, p=<optimized out>, have_lock=0) at ./malloc/malloc.c:4541 #8 0x00007ffff78addae in __GI___libc_free (mem=0x55555558f2b0) at ./malloc/malloc.c:3398 #9 0x0000555555558ab5 in operator() (frame_ptr=0x55555558f2b0) at int_coroutine.cpp:66 #10 0x00005555555588be in operator() () at int_coroutine.cpp:64 #11 0x0000555555558b2a in main () at int_coroutine.cpp:66