Consider the following code:
#include <string>
#include <vector>
struct Foo;
std::vector<Foo> v;
struct Foo {
std::string s = std::string(10000, 'x');
Foo() {}
Foo(int) { v.clear(); }
};
int main() {
v.resize(1); // required, otherwise no double free
v.reserve(2); // optional
v.emplace_back(10); // causes double free
}
Here I call v.emplace_back
which calls Foo(int)
which calls v.clear()
before emplace_back
is completed. Seemingly, std::vector
is unprepared for that mess and my implementation (Ubuntu 22.04's libstdc++) results in double free: v[0]
is first destroyed by clear()
, and later by v
's destructor.
What wording in any C++ standard makes the behavior of the program above undefined? I'm "simply" calling some operations on v
. I don't even access any elements of v
.
There is an active LWG issue 2414 to clarify reentrancy when different member functions of library objects are called. The current wording in [reentrancy] only specifies that it is implementation-defined which library functions are reentrant with regards to themselves (unless overruled by more specific rules).