https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107555
Bug ID: 107555 Summary: Never constructed object destroyed during exception handling Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: boris at kolpackov dot net Target Milestone: --- I have a fairly complex function (nested loops, try-catch blocks, etc) that on throwing an exceptions tries to destroy a stack object (suspected to be the return value) that was never constructed. This feels like a mis-compilation introduced in GCC 12 because: 1. The issue disappears if optimization is enabled. 2. The issue disappears if I get rid of the return value with otherwise minimal changes. 3. Does not reproduce with GCC 11 or 10 in otherwise the same build. I am not sure what's the best way to debug this. Coming up with a minimal reproduce feels hopeless. But I can easily provide the instructions on how to reproduce this on the actual source code. In the meantime, I will capture some background below: The relevant fragment of the stack trace looks like this: #18 0x00007f7472e5d270 in std::pair<build2::file_cache::entry, bool>::~pair (this=0x7ffdbe099e30, __in_chrg=<optimized out>) at /usr/include/c++/12/bits/stl_pair.h:185 #19 0x00007f7472e4ab19 in build2::cc::compile_rule::extract_headers (....) at .../compile-rule.cxx:4768 The pair object being destroyed at frame #18 was never constructed and eventually leads to "free(): invalid pointer" and abort. The extract_headers() function has the following overall structure (only what I believe are the relevant parts are shown): pair<file_cache::entry, bool> compile_rule:: extract_headers (....) { ... if (something) return make_pair (file_cache::entry (), false); // <-- one of early returns ... try { ... if (something) throw failed (); // <-- the exception that is thrown } // <-- line 4768 catch (const process_error& e) { ... throw failed (); } ... return make_pair (move (psrc), puse); } As can be seen, the function has a bunch of early returns. Other than the returns, it does not construct any pair<file_cache::entry, bool> instances. The call site look like this: pair<file_cache::entry, bool> psrc (file_cache::entry (), false); if (something) { ... psrc = extract_headers (....); } Note that I checked and the `this` pointer from frame #18 does not point to psrc form the call site. I was able to work around this issue by getting rid of the return type and instead passing the result object by reference: void compile_rule:: extract_headers (...., pair<file_cache::entry, bool>& result) { ... if (something) return; ... result.first = move (psrc); result.second = puse; } And the call site: pair<file_cache::entry, bool> psrc (file_cache::entry (), false); if (something) { ... extract_headers (...., psrc); }