Memory management with pointers created using "new" in C++ - c++

I have a base class where 2 pointers are declared in the header. The pointers are then initialized with the "new" keyword in a method of the base class and deleted with "delete" in the destructor of the base class.
I also have a derived class that inherits from the base class. I declare a pointer there as well. Depending on a boolean, this pointer is assigned to either pointer of the base class. However, this results in a segfault when the destructor of the base class is called.
My understanding is that this happens because the derived class will delete the pointer automatically before the destructor of the base class is called. When "delete" is called in the base class, then this area of memory has already been freed and a segfault results.
What is the correct way of doing this? My aim is to have a pointer in the derived class that can flexibly equal one of the pointers initialized in the base class.

Either do not delete the pointer in the derived class or use standard smart pointer std::shared_ptr

Your base class should probably have a virtual destructor, then you should override the destructor in your derived class to make sure everything gets deleted in the order you expect.
But it's hard to tell what's happening without seeing the code, so that's just a thought...

Related

Why the inheritance of a class with non-virtual destructor is not a good thing even if the derived class adds no members?

In this answer answer:
In particular, you are not allowed to delete a std::vector<T>* that
actually points at a derived object (even if the derived class adds no
members), yet the compiler generally can't warn you about it.
I understand that virtual destructor is needed if the object will be deleted through a base pointer. That's to let each class destroy it's members (at least I think so). But if the class don't have any members in itself, then why it shouldn't be deleted through the base pointer?
And also, how do I force some class to be accessed only through a pointer with it's type and not with one of the bases? will this make it normal to inherit from a class with a non-virtual destructor?

Virtual destructor use cases

I' ve read some articles, and as they say, main virtual destructor use cases are:
derived classes may have dynamic data allocation from heap, i.e. "own" that data object. So, they need some deletion routine in destructor. Deletion through base class pointer requires virtual declaration of destructors in all derived class till those with dynamic data allocation (base class also requires it)
this class has virtual methods. But this is unclear for me. Just calling virtual methods through base class pointer always results in the-most-derived-realization calls. They only exclusion for that rule is construction phase. Literaly, during it this object is not a derived type yet, even if later will be. Ok, what about destruction phase? As I understood, the rule is in the backward order. No matter, was destructor of some class in hierarchy declared as virtual, during each destructor this pointer is used as if of this class type, any derived were already been destroyed due to virtual d-r, or not destroyed (and that hypothetically may be ok in some design). Maybe this is the case, why d-r must be virtual? Vtable will have entries for derived class, and calling virtual methods in some base class from d-r will result in UB? Ok, but this rule applies only to case when this class calls some virtual methods in d-r, and they do have realization in derived classes.
My opinion, that there is also may be a case with no dynamic data allocation, no virtual methods in all hierarchy, but still derived destructors may do some critical tasks upon deletion (syncs, unlocks and so on). And we need virtual d-r in base class. May be such cases are results of bad design.
But anyway, developer of some public class cannot 100% know, if derived class will or not use some virtual methods in d-r, or allocate dynamic data. So, am I correct to say, that any public class, not declared as final, has to declare d-r as virtual? Only final keyword guarantees that any pointer to this class will always be of this type, and so, could be safely deleted non-virtually.
If a derived object is deleted through a pointer to the base class, then (and only then) the base class destructor must be virtual. Otherwise it is undefined behaviour. There are no other relevant rules.
If the class had a virtual function anyway, then no overhead is introduced. If the class did not have any other virtual functions, then the base class designer has to consider the trade between adding the runtime penalty of a virtual destructor, vs. the risk that a user of the class might try to delete a derived object through the base class pointer.
Here is a link to a similar discussion, with Standard quotes

Basic polymorphic pointers to base classes

While I've been working in c++ for a while, I haven't had need to use polymorphic features until now, and I'm very intrigued by them.
If I have a base class ClassA and another ClassB derives from it, I understand that I can have virtual member function in ClassA that, when implemented in ClassB, will be called in a ClassB instance even if that instance is pointed at using a ClassA pointer. Without this virtual keyword, I presume the base class implementation would prevail when using a base class pointer, yet be operating on an object that was instantiated from the subclass, which seems questionable to me if in fact ClassB has its own implementation of the same function that is effectively ignored in such a case.
Is this a correct understanding of polymorphic behavior?
Now the real question is how do you refer to ClassB using a pointer to is base class. I can really only think of two ways:
Create the pointer at the time of instantiation, using a function that returns a base class pointer while actually allocating memory for the subclass instead, using the subclass's constructor. (Does such a creation function have a common name?)
Casting an object using static_cast and assigning it to a pointer to the base class.
Are these the two main techniques for generating base class pointers to objects of a subclass?
The easiest way is to simply assign it, no cast necessary:
ClassA *ptrA = new ClassB;
You're correct that you need the virtual keyword to enable polymorphic behavior. Here's one way to think about it. C++ operates on the static type of an object. When you call ptrA->foo(), the type of the pointer is ClassA*. If that function is not declared virtual, then it will blindly call ClassA's version of the function. There's no other choice. But if foo() is virtual, then it knows to stop and ask, "Wait, what type am I really?" And the answer in that case is ClassB, so it will call ClassB's version.
Also note that you don't need pointers to achieve this. Another common way you'll see polymorphism in action is via a function call:
void bar(ClassA &aObj)
{
aObj.foo();
}
// ...
ClassB bObj;
bar(bObj);

Freeing abstract class pointers

In C++ I have a class A that has an abstract class pointer to allow for polymorphism contained in a class B, I have another pointer to an abstract class C that allocates a concrete instance of a child class of class B into that memory and I need to call a cleanup (see question below) function from class C to deallocate the memory taken by the child class of class B that I allocated from the heap, the problem is I can't guarantee I have access to the cleanup function because I only have a pointer to class C which I can't just copy, because it could be gone by the time I call need to destroy the containing class A.
In order to solve the problem of not having access to the cleanup function can I call delete on the class A pointer even though I'm pointing to a child class? Does C++ new also store heap block size like malloc so that you can just delete memory referenced by a pointer to an abstract class like this? If not is there another way to organize the program that allows me to handle the situation?
I'm using my crystal ball because it's hard to follow your question but you probably need virtual destructors.
The standard states (§5.3.5 ¶3):
In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
If I understood correctly, you have an object of some derived type, and you hold a pointer to it whose static type is one of its base classes; so, you're ok, as far as you have virtual destructors.
Edit well, I was way too slow :P

How are constructors and destructors implemented in C++?

I have 2 classes Base and Derived (derived publically from Base).
When I write -
Derived * d1 = new Derived;
delete d1;
Compiler sees that d1 is a Derived type object. So it calls the derived class constructor (which calls the base class constructor). I have 2 questions here -
1) Why do we follow this order?
2) How do these constructors work together to allocate memory? I need some implementation details
Now the next statement is delete d1. So compiler sees that d1 is a derived type object and so calls the destuctor of derived class (which calls the destructor of base class after deleting the derived class members). I have one question here -
1) How do these destructors work together? Lets say the derived class destructor is passed the address of d1 in memory. How do these destructors free up the space now?
That code will not compile. You cannot deletean automatic instance, you must use new to allocate the instance in order to use delete on it.
When it comes to constructor order, I guess it just makes sense to run them so that more specialized classes can depend on the more general parts having already been done.
The memory layout of each class is known by the compiler, from inspecting the complete class declaration and recursing up through any and all superclasses.
1) By default, the base class constructor is called automatically. However, the derived constructor is allowed to call the base class constructor explicitly in its initializer list. This would not be possible if the constructors were not executed derived-class-first.
Derived::Derived() : foo( 42 ), bar( 7 ), Base( 1, 2 ) { }
2) The compiler knows the memory footprint of the derived class (as all member variables are known at compile time), and allocates enough memory to hold both the base class and the derived class members. Details on the memory layout are specified by the ABI used by your system.
3) Destructors do more than just freeing up the memory. Actually, the destructors do not free up memory required to hold any member variables - only, where necessary, memory that member pointers point to.
(1) The base class does not depend on the derived class, but the other way around is possible. I.e. a Base class cannot know which fields any Derived class has, so Base::Base won't and can't touch them. The other way around is possible, Derived::Derived can access Base::member. Therefore, Base::member is initialized by Base::Base before Derived::Derived gets the chance to useBase::member`.
(2) constructors don't allocate memory. That's new's task. Or if the object is a global, the compilers'. The constructor is called with this already pointing to the allocated memory; it need just fill in the members at that location.
In the case of a base and derived constructor, one common implementation inserts the call to the Base constructor in the generated code for the Derived constructor. With single inheritance, the Base and Derived class usually share the same this pointer, so the Derived constrcutor can then pass the same pointer that it got.
(1) [sic] Just like constructors don't allocate memory, destructors don't free it. That's the task of delete - and again, for globals the compiler would do it.
The code example you give wouldn't compile. delete works on pointers, not objects.
I don't think C++ itself (the language standard) says anything about how memory is used to represent instances of types that use inheritance. However, in most implementations a single chunk of memory is allocated from the free store that is large enough to hold all the data of Base and Derived. When an instance of Derived is deleted, both constructors run and then the single memory block is freed.
Similarly, if an instance of Derived is an embedded data member of some class Container, then the memory block that holds an instance of Container will be made large enough to hold Derived (and hence Base) and all the other data of Container.
When constructing, constructors are called from the highest base class until the oneof the most derived, which will be called the latest.
When destructors are called, it's the reverse order. First is called the destuctor of the most derived, until the one of the highest base class.
While in inheritance, the compiler should know what it is inheriting. It should know what the Base class consists of. It cannot inherit from a class, which it doesn't have any idea..
So, it does make sense that the Base class constructor is called first and then the Derived.
And in the case of Destruction, if the Base destructor is being called first and gets destructed, the Derived class may still be using the Base class members which becomes invalid.. Hence the Destruction is the exact inverse of the construction..