Say I have something like this:
a = new A();
a->b = new B();
a->b->c = new C();
If I call:
delete(a)
Would it also delete b and c from memory? How can I be sure that all of them are gone?
This is a question that came up in one of my college classes, made by another student. No more info is given. I guess there is no definitive answer then, because I cannot tell you about the A,B or C destructors
Use
class A
{
std::shared_ptr<B> b;
}
You don't need destructor for A or B. Default ones will do.
Create destructor for A and B.
use smart pointer std::unique_ptr (or std::shared_ptr).
if you have such code in your program:
a = new A();
a->b = new B();
a->b->c = new C();
you need to (re)learn how to program in C++ properly. Member b of a and member c of b should be initialized by their constructor, not directly. When you write a constructor that use dynamic memory you should immediately think about memory management - either through smart pointers or properly following rule of three/five/zero
After you do that there would be no question if memory would be cleaned properly when a is destroyed.
Would it also delete b and c from memory?
Only if A's destructor contains code to explicitly do that or if b is some kind of smart pointer that takes care of it (and can accept the assignment). E.g.:
class A {
B *b;
~A() {
delete b;
}
};
How can I be sure that all of them are gone?
Presumably you're asking about best practices for avoiding leaks.
Don't use naked new/delete.
The entity responsible for allocating resources should always also be responsible for deallocating them.
Use RAII.
Without any info on how the destructors are defined, then it is true that there is no definitive answer. If there are no explicitly defined destructors, then the default destructors are used, and the code would cause memory leaks. If destructors are properly defined for those classes, then yes, delete(a) should delete b and c from memory.
So in other words, if something like this is defined in the code:
B::~B() { delete c; }
A::~A() { delete b; }
then the answer is yes. If not, the answer is no. If you don't know, then the answer is you can't know.
Related
Let's assume I have three classes:
class A{
};
class B{
int S;
A* arr;
B(int s):S(s){
arr = new A[S];
}
~B(){
delete [] arr;
}
};
class C{
B& b;
C(B& b): b(b){}
};
Should I define explicitly a destructor in class C? What would it look like?
Should I define explicitly a destructor in class C?
To answer that question, you must know what your class does. Is the purpose of the class to manage allocated memory? Then, yes you probably need a destructor. Is the purpose to refer to an object managed by something else? Then why would you need a destructor? If you don't know what a destructor should do, then you quite often do not need one.
You should never use owning references, so there should be little reason for C to have a destructor, or it has to be changed drastically.
You also should not use owning bare pointers, so class B should also be changed. Easiest solution is to replace it with std::vector.
No, you don't need a destructor for C, but you do need a copy-constructor (as well as a move-constructor, copy-assignment operator and move-assignment operator) for class B if you want to correctly implement copy-semantics. As it is now if you were to make a copy of an object of class B, you would have to objects pointing to the same array - when the objects are destructed you would get a double delete causing undefined behavior.
You don't need to use a raw pointer. You can simply use a std::vector will handle the allocation of the elements as well as its destruction. That also means that you won't need to implement any other kinds of constructors or a destructor for B since std::vector handles copies and moves correctly.
So I was looking at this question Memory Allocation Exception in Constructor where my boss states in his beautiful answer that the destructor will not be called.
Which makes me wonder,
If I were to write
struct XBase
{
int* a;
char* b;
float* c;
XBase() : a(nullptr), b(nullptr), c(nullptr) {}
~XBase()
{
delete[] a; delete[] b; delete[] c;
}
};
and
struct X : XBase
{
X() {
a = new int[100];
b = new char[100];
c = new float[100];
}
}
Then, if the allocation of c fails (with an exception being thrown), then the destructor of XBase would be called, since the base class has been constructed.
And no memory leak?
Am I correct?
You are right; this will work, because:
By the time X constructor body is executed, XBase is already constructed, and its destructor will be called.
Doing delete or delete[] on null pointers is perfectly valid, and does nothing.
So, if the allocation of a, b or c fails, the destructor of XBase will deallocate everything.
But, obviously, this design makes you write much more code that needed, since you can simply use std::vector or std::unique_ptr<T[]>.
Just to have a formal version here to back up the claims,
ยง 15.2/2
An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects [...].
If you're concerned about the memory allocation failing, I would put it in a separate method, like a Build or Create. You could then let the destructor handle it if it has been initialized (but definitely check pointer before blindly delete-ing.
Another solution is smart pointers, which are not designed to fit this case necessarily, but do automatically deallocate their contents.
I am trying to understand the below program . While executing am getting errors as shown below.
#include<iostream>
using namespace std;
class Base
{
public:
int *a;
int a1;
int b;
Base(){
cout<<"Inside Constructor"<<endl;
a1 = 10;
a = &a1;
cout<<" "<<a<<endl;
b = 20;
}
Base(const Base &rhs)
{
cout<<"Inside Copy Constructor"<<endl;
a = new int;
*a = *(rhs.a);
b = rhs.b;
}
~Base(void)
{
cout<<"Inside destructor"<<endl;
delete a;
}
};
int main()
{
Base obj;
Base obj2(obj);
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
obj.a1 = 30;
obj.b = 40;
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
return 0;
}
While executing this code i am getting the following output
Inside Constructor
Inside Copy Constructor
obj a 10 b 20
obj2 a 10 b 20
obj a 30 b 40
obj2 a 10 b 20
Inside destructor
Inside destructor
Segmentation fault
[EDIT]
I was looking for a way to destruct the heap memory that i have created in copy constructor . So what can be done here ? please suggest
[EDIT]
delete should be used on memory allocated from heap using new only.
a1 = 10;
a = &a1;
In your case "a" is holding the address of memory in stack. So, you shouldn't call delete on that memory.
You have to delete memory acquired with new (dynamically allocated), not to an automatic-storage variable.
In copy constructor you are using new operator to assign the memory for pointer a ,so u can delete it.But since u are not using new operator in default constructor, you can delete the pointer a .
You must use delete opearator to free the memory of variable which is in heap not in stack.
when you use new operator ,the variable is created in heap where as local variable are created in stack memory which can't be delete using delete operator
The problem is not the copy constructor, the problem is that you don't consistently use new (if you used move then maybe you would have a point). You have some options. I am trying to be useful, not exhaustive, maybe I'm missing other good design ideas.
Use new always (and consistently)
You can put a new in all the constructors, and thus, the destructor would always be able to call to delete. Even when you don't need it. It may be a ugly hack, but is consistent.
Never use new
If you never use new, you don't use delete either and the compiler ensures consistency and ensures that you don't mess up. Normally, you can rely on the compiler default behaviour on constructors.
Use smart pointers
If instead of calling to delete manually you save the variable inside a unique_ptr, then it will be deallocated at the destructor automatically by the compiler. The smart pointer is smart enough to know if it is initialized.
Beware that using a smart pointer means that you should never call delete, because if you do so without warning the smart pointer, you will stumble onto the same problem. If you are not familiarized with them and you are using C++11, it is a nice thing to learn :)
Track the status of your pointers
I would not vouch for this. It seems very C and not C++. However, you can always track a bool value and at destroy time check it. This is just like using smart pointers, but with an in-house implementation. I think that it is a bad design idea, although educational in some cases.
I cannot resolve the following issue by myself:
Suppose we are reusing a memory in a following way:
struct A
{
int a;
A(){ }
~A(){ }
};
struct B : A
{
int b;
B(){ }
~B(){ }
};
A *a = (A*) malloc(sizeof(A) + sizeof(B));
B *b = new (a) B; //Constructor of B is calling
The lifetime of object reffered to by a has ended before the constructor of B is starting to call or it has ended when the constructor of B has finished?
You try to use the placement new operator to initialize b. This operator does not call the destructor of class A first (a), but initializes a new one into the memory pointed to by a. This is problematic (as mentioned in the comment), because the sizeof(B) is greater than sizeof(A) and you allocated only sizeof(A) at the pointer a. So it is undefined behavior.
The lifetime of the object a formally does not end. You get something like:
class A { int a; };
void* p = malloc(sizeof(A));
A* a1 = new (p) A();
A* a2 = new (p) A();
I think, you will get something like double called destructor on the same memory, but that is something compiler-implementation specific. I don't think, that the standard does say anything about this.
As soon as you enter the constructor of B, a is not pointing to an object A any more.
The reason is that even before the first instruction of the constructor of an object the runtime already has done the VMT, base sub-objects and member initialization.
Also if the constructor of B doesn't terminate because of an exception the memory has already been used anyway and another object eventually present at the same memory address doesn't exist any more.
In other words just don't do that... in C++ objects are not just a pile of bytes and they have rights; for example the right of having their destructor called ;-)
The standard from the relevant section (3.8) says,
The lifetime of an object of type T ends when:
- if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
- the storage which the object occupies is reused or released.
I interpret to mean that the life time of the object pointed to by a ends when members of B are initialized. Until that happens, the storage is not reused.
The lifetime of a ends when you delete it and not before - since forcing two different objects to occupy the same space this way is itself undefined behaviour and definitely not recommended your compiler may or may not treat that memory as available for reuse and overwrite b.
If you need to have two objects occupying the same location, e.g.: Message Variants or you are trying to write your own debugger then you should use a union type.
The other reason that you are not recommended to do this sort of thing is that you will create a maintenance nightmare. e.g. later in your code you could have:
b.b = 3
while (a.a > 0) {
b.b--;
}
I have a class MyClassA. In its constructur, I am passing the pointer to instance of class B. I have some very basic questions related to this.
(1) First thing , is the following code correct? ( the code that makes a shallow copy and the code in methodA())
MyClassA::MyClassA(B *b){
this.b = b;
}
void MyClassA::methodA(){
int i;
i = b.getFooValue();
// Should I rather be using the arrow operator here??
// i = b->getFooValue()
}
(2) I am guessing I don't need to worry about deleting memory for MyClassA.b in the destructor ~MyClassA() as it is not allocated. Am I right?
thanks
Update: Thank you all for your answers! MyclassA is only interested in accessing the methods of class B. It is not taking ownership of B.
You need the arrow operator since b is a pointer.
Yes, unless the user of MyClassA expects to take the ownership of b. (You can't even be sure if b is a stack variable where delete-ing it will may the code crash.)
Why don't you use a smart pointer, or even simpler, a reference?
First thing , is the following code
correct? ( the code that makes a
shallow copy and the code in
methodA())
The answer depends upon who owns the responsibility of the B object's memory. If MyClassA is supposed just to store the pointer of A without holding the responsibility to delete it then it is fine. Otherwise, you need to do the deep copy.
I am guessing I don't need to worry
about deleting memory for MyClassA.b
in the destructor ~MyClassA() as it is
not allocated. Am I right?
Again depends on how memory for B is allocated. Is it allocated on stack or heap? If from stack then you need not explicitly free it in destructor of MyClassA, otherwise you need to to delete it.
1) . It depends on the life time of the pointer to B.
Make sure the when you call b->getFooValue(); b should be a valid pointer.
I will suggest use of initilization list and if you are only reading the value of the B object though it pointer then make it pointer to constant data.
MyClassA::MyClassA(const B *bObj) : b(bObj)
{}
2). As long as B is on the stack on need to delete it and if it is allocated to heap then it must be deleted by it the owner else you will have memory leak.
You can use smart pointer to get rid of the problem.
MyClassA::MyClassA(B *b){
this.b = b;
}
should be:
MyClassA::MyClassA(B *b){
this->b = b;
}
because this is treated as a pointer.
1)
this.b = b;
Here you pass a pointer to an instance of B. As Mac notes, this should be:
this->b = b;
b.getFooValue();
This should be b->getFooValue(), because MyClassA::b is a pointer to B.
2) This depends of how you define what MyClassA::b is. If you specify (in code comments) that MyClassA takes over ownership over the B instance passed in MyClassA's constructor, then you'll need to delete b in MyClassA's destructor. If you specify that it only keeps a reference to b, without taking over the ownership, then you don't have to.
PS. Regrettably, in your example there is no way to make ownership explicit other than in code documentation.