Why are there no memleaks in the following C ++ on assignment?

The following code lowers my belief that I know C ++ more or less. Why valgrind does not display memleak here? Why I expect memleaks:

  • B larger than A : it contains an additional element; therefore, assignment must be separated by class fields.
  • ~ A () does not have a virtual dtor. Therefore, when we call delete a , only ~A() should be called, and the memory allocated in B will be lost.

But I get that dtors calling order: ~ A (), ~ B (), ~ A (). Why?

 struct A { ~A() { std::cerr << "~A" << std::endl; } }; struct B : A { int* data; B() : data(new int[20]) {} ~B() { std::cerr << "~B" << std::endl; delete [] data; } }; 

main() :

 A* a = new A; B* b = new B; *a = *b; delete a; delete b; 

UPD: I am ashamed! I confused the removal of an object with a pointer to the base class when it was supposed to call a virtual dtor. Here is just the contents of the class. Thanks everyone!

+4
source share
7 answers
 delete a; 

a A* , therefore A::~A is called

 delete b; 

b B* , so B::~B is invoked.

Why is there a problem?

Fields of fields of fields? Huh? You just copy fields a from *b to *a , nothing more. There is no memory.

+5
source

In *a = *b you copy (and yes, chop) *b to *a . However, this leaves *b unchanged; it is not chopped. When you delete b , you ask ~B() call on *b .

+1
source

Purpose *a = *b; copies only the common part A data (and A has no fields).

+1
source

You did a deletion for every new one, so there is no memleak.

 *a =*b 

doesn't highlight anything, the copy constructor just copies part b, which can go to a, but it doesn't call a new one.

0
source

By calling *a = *b; , you implicitly invoke the assignment operator created by the compiler, which looks like this:

 A &operator=( const A &other ){ } 

which in your case does nothing, since A does not have a member variable.

0
source

Your class A empty, so it is completely irrelevant to the purpose of this discussion. The only code that is involved in dynamic allocation:

 B* b = new B; delete b; 

Since you delete an object created with new , there is no leak. In addition, class B contains enough code to clear its own internal distribution in this direct use case.

(Note that class B is still badly broken, as it will not survive copying or assignment. A classic rule of three (or five).)

0
source

Because you are cutting objects here. I think you intended to have a pointer to a base pointer to a derived object, and since the base destructor is not virtual, the destructor of the derived class is not called during cleanup. But here it is not.

 *a = *b 

The compiler will "cut" the derived part of the object and copy only the base part of the object. Usually this does not need to be done, because it will lead to an incomplete object with no properties of the base class and properties of a specialized derived class.

0
source

Source: https://habr.com/ru/post/1385289/


All Articles