Destructor not being called when leaving scope - c++

I am learning memory management in C++ and I don't get the why only some of the destructors are called when leaving scope. In the code below, only obj1 destructor is called when myfunc ends, not for the dynamically allocated obj2.
int myfunc (cl1 *oarg) {
cout << "myfunc called" << std::endl;
cl1 obj1(222,"NY");
cl1 *obj2;
obj2= new cl1;
oarg->disp();
obj2 -> ~cl1 ;
}
Here is the destructor I have :
cl1 :: ~cl1 () {
std::cout<< " cl1 destructor called"<<std::endl;
std::cout << this->data << std::endl; //just to identify the obj
delete [] str;
str = NULL ;
};

If you allocate a object using new
obj2= new cl1;
Then unless you call delete on it, its destructor won't be called implicitly.
EDIT: As #David, meantions in comments, One may call destructor of an object explicitly but in my experience there is rarely a need to manually call the destructor unless one is using placement new version of new.
Variables on stack are implicitly cleaned up(by calling their destructors) when their scope ends.
Dynamically allocated objects are not implicitly cleaned, it is the responsibility of the user to clean them up explicitly calling delete.
This is the very reason one should not use raw pointers but use smart pointers.

Dynamically allocated objects are your responsibility - you need to explicitly clean them up. Automatic objects (such as obj1) are cleaned up when the scope exits, automatically. In this case, before the scope exits - explicitly call delete obj2. NOTE: this line obj2 -> ~cl1 - does not do anything - the delete will take care of triggering the destructor correctly.

obj1 is an object of type cl1, with automatic storage duration (It is allocated on the stack, and its lifetime is determined by the scope it is in)
obj1 is an object of type cl1*. That is, it is a pointer. The pointer also has automatic storage duration, but the object it points to does not. It points to a dynamically-allocated object in the free-store.
When you leave the scope, then the objects with automatic storage duration get destroyed. obj1 gets destroyed, calling your destructor. And obj2 also gets destroyed, but obj2 isn't of type cl1, so it doesn't call cl1's destructor. It is a pointer, and it does nothing special when it is destroyed.
Pointers don't own the objects they point to, and so they do nothing to ensure the pointed-to object gets destroyed or cleaned up. (If you want an "owning" pointer, that's what smart pointer classes are for)
Consider that you can easily have multiple pointers pointing to the same object.
If a pointer automatically deleted the object it pointed to, then that would lead to errors. An object pointed to by two different pointers would get deleted twice.

obj2 -> ~cl1 ;
Don't do this! Use delete obj2; instead.
Addendum
What you were trying to do was to call the destructor explicitly. Your code does not do that. Your code is getting the address of the destructor and then dropping it into the bit bucket. Your code is a no-op. The correct way to explicitly call the destructor is obj2->~cli();.
Explicitly calling the destructor is usually something you should not do.
What you should do is to delete the memory created by new. The correct way to do that is to use the delete operator. This automatically calls the destructor and releases the memory. The destructor does not release the memory. Failing to use delete results in a memory leak.

Destructors are called automatically when an object that was created on the stack goes out of scope.
With dynamically allocated objects, you need to call delete obj. delete will automatically call your destructor for you.

You should use delete for dynamically allocated objects:
delete obj2;
this calls the destructor and frees memory. You'll be much better off using smart pointers for managing such objects - they will call delete for you even in case of exception being thrown between new and delete.

First of all you should use delete operator to destrory an object and not call its destructor directtly. Secondly, by doing new you are telling the compiler that you dont want to delete the object when it goes out of the scope. In such case you need to explictly fo delete objj2; to delete the object.

Use std::unique_ptr or std::shared_ptr instead of raw pointer.
It the best way to avoid memory leaks or double free.
That is the right way in modern C++.
int myfunc (cl1 *oarg)
{
cout << "myfunc called" << std::endl;
cl1 obj1(222,"NY");
std::unique_ptr<cl1> obj2( new cl1 );
oarg->disp();
}

Related

The difference between a destructor and 'delete'

What is the difference between the destruction of an object and deletion in C++? In OOP, when an object goes out of the scope, the destructor is called, and when dynamically allocating memory we have to use the delete keyword inside the destructor. So what does it mean for an object to be destroyed or deleted?
A destructor is a special method for a class. It is called whenever an object goes out of scope, or someone calls it explicitly.
An example where an objects destructor is called, but no delete:
struct MyObject
{
MyObject() { std::cout << "default constructor"; }
~MyObject() { std::cout << "destructor"; }
void doWork() {};
}
int main()
{
{
MyObject object; //constructor is called and memory allocated for the object on the stack
object.doWork();
} //at the end of scope, the destructor of MyObject is called, and the stack memory is "released"
// object is not longer available and stack memory is free
}
An example when scope does not help you:
int main()
{
{
MyObject* object_ptr = new MyObject; //constructor is called and memory allocated on the heap. The pointer_ptr object
object_ptr->doWork();
} //at the end of scope the object_ptr is removed from the stack, but the destructor for the MyObject is not called!
// object_ptr is no longer available.
}
For the above example, we have an issue with the dynamically allocated memory. We explicitly call the destructor of the object we are pointing to by calling delete (and freeing the memory where MyObject is residing!):
int main()
{
{
MyObject* object_ptr = new MyObject; //constructor is called and memory allocated on the heap. The pointer_ptr object
object_ptr->doWork();
delete object_ptr; // destructor of MyObject is called and memory freed.
// object_ptr is still usable here, but it is pointing at an destroyed object, so don't use it! (unless you redirect it)
}
}
So delete is for managing the dynamic memory, but the destructor is a method of the class itself, which is always called when the object is getting freed from the memory (stack or heap). The destructor is called when freeing the memory for the object, so that if the object itself handles memory, is has time to release that memory. That's why smart pointers are good:
int main()
{
{
std::unique_ptr<MyObject> object_ptr = std::make_unique<MyObject>(); //constructor is called and memory allocated on the heap. The pointer_ptr object
object_ptr->doWork();
} //destructor for std::unique_ptr<MyObject> is called, which in turn calls delete on the object it is pointing at, which calls the destructor of that object!
}
There are multiple ways for memory allocation some of them are:
Automatic memory allocation :
In this case ,the variables defined inside a scope ,for example functions, are automatic allocated, and is usually stored on the stack. You have a limited control over the lifetime of this memory. E.g: automatic variables in a function are only there until the function finishes, then when going out of that scope, their destructors are called automatically i.e. you must not call delete to free the memory reserved for that object.
Dynamic memory allocation :
In this case , the variables defined inside a scope ,for example functions, are dynamically allocated. You control the size and the lifetime of these memory locations. If you don't free the reserved memory (delete it), the allocated memory is still valid and accessible, even though the function terminated (went out of scope) and in this case you'll have memory leakage, which may cause the program to crash. So the object should be delete explicitly which in turn will call the destructor for that object.
In the same way that a constructor is only part of the process of creating an object, invoking the destructor is just part of the process of destroying an object. It is a place where special clean-up code can go, like closing file handles or destroying other, indirectly-owned objects.
delete is the way you trigger the deletion of a dynamically allocated object. Other types of object are deleted automatically when they go out of scope. This keyword will clean up memory and more abstractly end the object's lifetime so that the compiler knows it doesn't conceptually "exist" any more.
You generally don't call the destructor manually, as it is usually insufficient for safely ending the lifetime of an object on its own. However, doing so is useful when you're taking super-fine-grained control over objects' existences, with (for example) placement new: then, it can be sufficient. But this is a special case.
When an object is destroyed it's destructor is called. A pointer to a dynamically allocated memory can be deleted, objects themselves can't be deleted (unless you think of a pointer as a kind of object).
Either of these actions can have knock on effects that cause the other action to happen (or more instances of the same action). For instance if you delete a pointer to an object, then the objects destructor will be called (if it has one) and it's destructor may cause other pointers to be deleted and other objects to be destroyed.
Basically destructor is about the death of objects and deletion is about the freeing of dynamically allocated memory, but the two actions are often intertwined.

Calling destructor to free dynamically allocated memory

Let consider this code:
#include <iostream>
class A{
public:
~A() {}
};
int main(){
A *p = new A();
p->~A();
return 0;
}
I would like to know if the memory of the object A pointed by p is freed or we must to call delete p;
The memory was not freed. The destructor destroys the object but does not free the memory. How could it? You can destroy objects that are dynamically allocated, are on the stack, are globals, and so on. The destructor has no idea what is needed, if anything, to release the memory.
Memory was allocated using operator new and will be freed (deallocated) using operator delete, not your object's destructor.
We should not confuse the object lifetime with dynamic memory management.
It is not A's destructor role to free the allocated memory and it should not be called explicitly. It is simply a member function that gets called when your object gets destroyed. And it will get destroyed after you call the delete.
Replace:
p->~A();
with:
delete p;
Now your objects gets destroyed and the allocated memory gets deallocated.
There is no difference between calling destructor or any other member function, except one thing - you should not do it, unless you want to separate object allocation from its construction and destruction.

Why not call Destructor in C++?

I studding C++ concept. I'm confused in constructor and Destractor concept. Destructor will be invoked implicitly by the compiler upon exit from the program. But in my program, only constructor called.
#include <iostream>
using namespace std;
class A
{
int i;
public:
A()
{
cout<<"Constructor call"<<endl;
}
~A()
{
cout<<"Destructtor call"<<endl;
}
};
int main()
{
A *a = new A();
}
Output:
Constructor call
So, I have question : Why destructor not call implicit by the compiler upon exit program?
Why destructor not call implicit by the compiler upon exit program?
Because dynamically allocated objects are not destroyed automatically. That is how the language has been specified. Tracking the destruction of dynamic objects would require runtime / memory overhead.
Solution: Do not leak dynamically allocated objects.
There are 2 "types" of variable lifetime in C++. Dynamic and automatic.
Automatic is something like :
void foo()
{
int i; // automatic storage
} // destroys i
Here, i will be destructed the moment it leaves scope (after foo returns). You can check this for yourself by making your object have an automatic lifetime:
int main()
{
A a; // calls A's constructor and allocates memory.
} //calls A's destructor and frees the memory used.
You'll see that both the constructor and the destructor will get called.
The second form is dynamically allocated memory. You can dynamically allocate memory by using new (like you did) and free that memory by using delete. The compiler won't do this for you.
This means that, to destruct your object you have to call delete explicitly yourself:
int main()
{
A* a = new A();
delete a; // calls A's destructor and frees the memory used.
}
If you do not call delete (like your code) then the moment the program leaves main the pointer a is destroyed and now we have a piece of memory that nothing can reach and thus nobody can clean up (with delete) which means you're leaking memory.
However, modern operating systems reclaim all memory used by the program automatically the moment the program ends so at this point it won't matter too much. This does mean your destructor won't be called as you've just witnessed.
Dynamically allocated memory allows you to do some nifty tricks like controlling the lifetime of your objects to the point where you want to destroy them explicitly yourself with delete. The problem with using new and delete is that it's so easy to forget a single delete and your program will already leak memory, which is why it's advised to stay away from this way of allocation.
If for some reason you absolutely need dynamic lifetime then use a smart pointer like std::unique_ptr that will call new and delete for you the moment it goes out of scope.
You create the object dynamically with new. The destructor will only be called when the objected is deleted with delete.
To prevent memory leaks, you could/should use smart pointers like unique_ptr.
In any case, the memory itself will of course be released when the process ends.
The destructor is never called in your code because the object is never destroyed.
You dynamically allocate the A object and you never deallocate it. Add delete a; into main() and you'll see the destructor in action:
int main()
{
A *a = new A();
delete a;
return 0;
}
In your main function, you create a pointer variable that you must delete it by delete a at end of main function.
Because you have a memory leak. You dynamically created an object with new, promising that you would manage the lifetime of the object and clean it up later with delete. Then you broke that promise.
If you create an object in the usual fashion:
A a;
then it will be destroyed automatically for you.

How to manually destroy member variables?

I have a basic question on destructors.
Suppose I have the following class
class A
{
public:
int z;
int* ptr;
A(){z=5 ; ptr = new int[3]; } ;
~A() {delete[] ptr;};
}
Now destructors are supposed to destroy an instantiation of an object.
The destructor above does exactly that, in freeing the dynamically alloctaed memory allocated by new.
But what about the variable z? How should I manually destroy it / free the memory allocated by z? Does it get destroyed automatically when the class goes out of scope?
It gets "destroyed" automatically, although since in your example int z is a POD-type, there is no explicit destructor ... the memory is simply reclaimed. Otherwise, if there was a destructor for the object, it would be called to properly clean-up the resources of that non-static data member after the body of the destructor for the main class A had completed, but not exited.
z is automatically destroyed. This happens for every "automatic" variable. Even for pointers like int*, float*, some_class*, etc. However, when raw pointers are destroyed, they are not automatically deleted. That's how smart pointers behave.
Because of that property, one should always use smart pointers to express ownership semantics. They also don't need any special mentioning in the copy / move constructor / assignment operator, most of the time you don't even need to write them when using smart pointers, as they do all that's needed by themselves.
Destroying an object will destroy all the member variables of that object too. You only need to delete the pointer because destroying a pointer doesn't do anything - in particular it doesn't destroy the object that the pointer points to or free its memory.
It does, in fact, get automatically destroyed when the class goes out of scope. A very good way to guess if that's the case is that there's no * after its declaration.
For PODS (plain old data types) like ints, floats and so on, they are automatically destroyed. If you have objects as data members (e.g. std::string aStr;), their destructors will be automatically called. You only have to manually handle memory freeing (like above) or any other manual object or data cleanup (like closing files, freeing resources and so on).

Is memory released when a destructor is called or when `delete` is called?

Assume you have an object of class Fool.
class Fool
{
int a,b,c;
double* array ;
//...
~Fool()
{
// destroys the array..
delete[] array ;
}
};
Fool *fool = new Fool() ;
Now, I know you shouldn't, but some fool calls the destructor on fool anyway. fool->~Fool();.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does that mean only whatever deallocations in ~Fool() function occur (ie the array is deleted only?)
So I guess my question is, is a destructor just another function that gets called when delete is called on an object, or does it do more?
If you write
fool->~Fool();
You end the object's lifetime, which invokes the destructor and reclaims the inner array array. The memory holding the object is not freed, however, which means that if you want to bring the object back to life using placement new:
new (fool) Fool;
you can do so.
According to the spec, reading or writing the values of the fields of fool after you explicitly invoke the destructor results in undefined behavior because the object's lifetime has ended, but the memory holding the object should still be allocated and you will need to free it by invoking operator delete:
fool->~Fool();
operator delete(fool);
The reason to use operator delete instead of just writing
delete fool;
is that the latter has undefined behavior, because fool's lifetime has already ended. Using the raw deallocation routine operator delete ensures that the memory is reclaimed without trying to do anything to end the object's lifetime.
Of course, if the memory for the object didn't come from new (perhaps it's stack-allocated, or perhaps you're using a custom allocator), then you shouldn't use operator delete to free it. If you did, you'd end up with undefined behavior (again!). This seems to be a recurring theme in this question. :-)
Hope this helps!
The destructor call does just that, it calls the destructor. Nothing more and nothing less. Allocation is separate from construction, and deallocation from destruction.
The typical sequence is this:
1. Allocate memory
2. Construct object
3. Destroy object (assuming no exception during construction)
4. Deallocate memory
In fact, if you run this manually, you will have to call the destructor yourself:
void * addr = ::operator new(sizeof(Fool));
Fool * fp = new (addr) Fool;
fp->~Fool();
::operator delete(addr);
The automatic way of writing this is of course Fool * fp = new Fool; delete fp;. The new expression invokes allocation and construction for you, and the delete expression calls the destructor and deallocates the memory.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does
that mean only whatever deallocations in ~Fool() function occur (ie
the array is deleted only?)
Fool::~Fool() has zero knowledge about whether the Fool instance is stored in dynamic storage (via new) or whether it is stored in automatic storage (i.e. stack objects). Since the object ceases to exist after the destructor is run, you can't assume that a, b, c and array will stay valid after the destructor exits.
However, because Fool::~Fool() knows nothing about how the Fool was allocated, calling the destructor directly on a new-allocated Fool will not free the underlying memory that backs the object.
You should not access a, b, and c after the destructor is called, even if it's an explicit destructor call. You never know what your compiler puts in your destructor that might make those values invalid.
However, the memory is not actually freed in the case of an explicit destructor call. This is by design; it allows an object constructed using placement new to be cleaned up.
Example:
char buf[sizeof (Fool)];
Fool* fool = new (buf) Fool; // fool points to buf
// ...
fool->~Fool();
The easiest place to see that the destructor is distinct from deallocation via delete is when the allocation is automatic in the first place:
{
Fool fool;
// ~Fool called on exit from block; nary a sign of new or delete
}
Note also the STL containers make full use of the explicit destructor call. For example, a std::vector<> treats storage and contained objects lifetime quite separately.