A couple of months ago I asked this question where I asked why there was a memory leak. Apparently, I forgot a virtual destructor.
Now I'm struggling to understand why this is not a memory leak:
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Base{
public:
explicit Base(double a){
a_ = a;
}
virtual void fun(){
cout << "Base " << a_ << endl;
}
protected:
double a_;
};
class Derived : public Base{
public:
Derived(double a, double b): Base(a), b_{b}{
}
void fun() override{
cout << "Derived " << a_ << endl;
}
private:
double b_;
};
int main() {
vector<unique_ptr<Base> > m;
for(int i=0; i<10; ++i){
if(i%2 == 0){
m.emplace_back(make_unique<Base>(i));
}else{
m.emplace_back(make_unique<Derived>(i, 2*i));
}
}
for(const auto &any:m){
any->fun();
}
return 0;
}
Note that I do not have a virtual destructor for Base.
I thought that because I have a vector m of type unique_ptr<Base> only the destructor from Base gets called and my variable b_ in Derived would leak but according to valgrind this is not the case.
Why is this not a memory leak?
I have tested this with valgrind-3.13.0
Deleting an object via a polymorphic pointer when the base class doesn't have a virtual destructor is undefined behaviour.
Undefined behaviour may mean your code leaks memory, crashes or works perfectly.
In this case the runtime library presumably allocated a single block of memory for your object and is able to delete that block correctly even when it is pointed to by a pointer of a different type. This is probably true for most runtimes but there are no guarantees. E.g. when using malloc() and free() you don't need to supply the size of the malloc() to free(), the same is happening here.
If you had defined a destructor in Derived you would see that it is not being called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With