[Bug c++/107555] New: Never constructed object destroyed during exception handling
boris at kolpackov dot net
gcc-bugzilla@gcc.gnu.org
Mon Nov 7 13:34:49 GMT 2022
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);
}
More information about the Gcc-bugs
mailing list