I read one answer about using std::vector::emplace_back on std::vector<std::unique_ptr<SomeClass>> and getting memory leaks when passing raw pointers (my_vec.emplace_back(new SomeClass())) in some exceptional scenario. Since that post is old (2016) and we have new standards now, I thought of trying an experiment if this issue is somehow fixed.
#include <iostream>
#include <memory>
#include <vector>
#include <limits>
struct MyClass
{
~MyClass() { std::cout << "Destroyed\n"; }
};
int main()
{
std::vector<std::unique_ptr<MyClass>> store;
auto limit = std::numeric_limits<uint32_t>::max();
std::cout << "Trying to allocate " << limit << " unqiue ptrs\n";
for (size_t i = 0; i < limit; i++)
{
store.emplace_back(new MyClass()); // THIS LINE
}
}
I saw that compilers didn't throw any errors or warnings for the line marked with the comment // THIS LINE.
It's been a long time since we know this issue. Of course, the solution to avoid this is to wrap those raw pointers around smart pointers. But still, if somebody attempts to use raw pointers anyway, then compilers should warn them which doesn't happen.
Is there any work ongoing regarding this? If there are already some ways to detect such issues, please share them.
Code link: https://godbolt.org/z/d5ooeEWf5
P.S. I thought of trying this experiment because I like C++ and I found Rust fans pointing out issues with C++ which makes me sad.
I don't get the problem -
emplace_backcan fail by throwing in strong-exception manner which is documented. In that case the passed arguments are not "consumed", i.e. they still belong to the caller.The fact that you forget to check whether the ownership was really passed to the function or remained with you is your problem, it's not the fault
std::vector,std::unique_ptror C++ design, it can happen to any resource, not just memory.I think you can get the same thing to happen in Rust if you use
unsafewhich using rawnewis no different from really.In modern C++, you should use raw pointers exactly because you want to do what you want to do, you are in your own.
new MyClass()mean I will manage the lifetime of this object myself.Sure, the compiler could issue a warning "passing a pointer to which there is no local reference to a function which can throw", feel free to contribute that to gcc, clang, they are open source after all. But doing such analysis without many false-positives might be very tricky.