free(f);
f->close();
in code that does a few malloc, if/else’s, etc. between those calls. Stuff like that gets hard to spot in more complex code, especially in the presence of C++ copy constructors, move constructors, etc, where the compiler helpfully inserts that call to free for you.Bugs in copy constructors also can lead to double frees when the destructors of an object and its copy both call delete on a pointer that they think they exclusively own. Between those two destructor calls, you can easily get a use after free. Example: https://stackoverflow.com/a/64014035
If the allocator doesn’t change the content of freed blocks, such bugs can go unnoticed, making the program “accidentally depend on freeing memory not immediately overwriting it”.
You only mean the former, not both. The only reason for the existence of the giant rats' nest of complexity that is C++ move semantics is eliminating this particular mistake.
char const* inputFilename = std::string("path/to/file").c_str();
call_to_C_API(inputFilename);
Boom. You can typically access `inputFilename` until the next allocation on the stack, but it will almost always go bad quickly. This isn't allocation on the heap, which usually requires another level of indirection, but you get the idea.Isn't it allocating in the stack due to the "small string optimization"? Making string contents longer (or using a C++ standard library which doesn't have a "small string optimization" in the first place) would be enough to have it be allocated in the heap instead.
Changing it to:
call_to_C_API(std::string("path/to/file").c_str());
Makes it valid because the std::string object will live until the semicolon.