Ensuring C++ Object is properly de-allocated - c++

I am beginning to teach myself C++ and how to handle objects without a garbage collector is causing me some confusion. Here is a simple case of what I am trying to do:
A* a;
B b = new B(a); // Note that B is a derived class of A
a = &b;
while (a != NULL)
{
(*a).run();
}
This all works as I expect it to. Where I am having the issue, is that inside the run() method of B, I want to do something like:
C c = new C(a); // a is the same pointer as above, that has been stored
// and C another derived class from A
a = &c;
and then let run() exit. The while loop in the first block would then call would call run() on the new object. My question is, how do I make sure that the memory from the original b is correctly de-allocated?

You could use std::shared_ptr in this case. If two classes have members which need to point to the same object, then you can make both of them shared_ptr. And you do this usually, however if while doing so, if you about to create cyclic-dependency, then to break that cyclic-dependency, you need std::weak_ptr.
Here is example of std::shared_ptr and std::weak_ptr.
WRONG CODE (cyclic-dependency):
struct B;
struct A
{
std::shared_ptr<B> bp;
}
struct B
{
std::shared_ptr<A> ba; //this creates a cyclic dependency.
}
CORRECT CODE (non-cyclic):
struct B;
struct A
{
std::shared_ptr<B> bp;
}
struct B
{
std::weak_ptr<A> ba; //break cyclic dependency with std::weak_ptr
}

Whenever you're faced with dynamic memory allocation and nontrivial ownership semantics, smart pointers are often a good way to ensure correctness.
See, for example, std::shared_ptr.

Related

Heap corruption on deleting a pointer twice stored in different classes

Two classes A and B share pointer to a third class C and when either A or B are deleted they call delete C as well.
Issue is not observed when only either of A or B is deleted.
An exception is getting thrown in this scenario. I have specifically tried to set the class C pointer to NULL and have put in a NULL check to avoid this specific scenario but this null check is somehow not working.
I have read around that shared pointer should be used in this case but I am not sure how to implement it properly. It looks like whole code base needs to be changed to include shared_ptr everywhere as all class C objects would be updated to shared_ptr. Is there a way I can use shared_ptr just to store this pointer without changing all the code?
Edit:
I have specifically deleted assignment operator and copy constructor of C to avoid situation both have different pointers due to copying. Can anything else can be done to prevent copying as pointed in answer by john
class A{
C* c;
}
~A(){
if(C != NULL){
delete C;
C = NULL;
}
}
class B{
C* c;
}
~B(){
if(C != NULL){
delete C;
C = NULL;
}
}
A and B have separate copies of the pointer to C. So setting one classes copy of that pointer to NULL has no effect on the other pointer and you still get a double delete.
You have basically four options
Decide that one class 'owns' the pointer, that class will delete it and the other will not. The danger here is that if the owning class deletes the pointer and then the non-owning class uses the pointer then you are going to get a different kind of error.
Use shared ownership of the pointer, so that it only gets deleted when the last object using it gets destroyed. The easy way to do that is to use std::shared_ptr
#include <memory>
class A {
std::shared_ptr<C> c;
};
class B {
std::shared_ptr<C> c;
};
Clone the pointer before copying it to the second class. Something roughly like
a.c = new C();
b.c = new C(*a.c);
this way both classes get separate (but equal) copies of the C object. But this changes the semantics of your program, maybe you actually want A and B to share the same C object.
This option (suggested by Richard Critten) has class A having a std::shared_ptr and class B having a std::weak_ptr. This means that A owns the C object, and when the last A object has been destroyed the C object will also be destroyed. Any remaining B objects do not prevent the destruction of the C object but, the B object can check whether the C object has been destroyed. In code it looks something like this
#include <memory>
class A
{
std::shared_ptr<C> c;
};
class B
{
std::weak_ptr<C> c;
};
class C
{
C(whatever);
};
A a;
B b;
// create a shared pointer
a.c = std::make_shared<C>(whatever);
// create a weak pointer referring to the same C object
b.c = a.c;
// create a shared pointer from the weak pointer in b
auto c = b.c.lock();
// check if the pointer is valid
if (c)
{
// do something with c
c->something();
}
else
{
// c object has been destroyed
}

C++ Pointers and Deletion

This is a simplified version of some code that I have. Since pointerB in class A is set to pointer, beta, in the client code which points to allocated memory, would i have to free the memory pointed by pointerB in the destructor of class A once it is deleted as well?
class A{
public:
A(B* beta){
pointerB = beta;
}
~A(){
/*
would deleting pointerB be necessary
*/
}
B* pointerB;
};
class B{
public:
B();
};
//client code
B* beta = new B();
A* alpha = new A(beta);
//do stuff
delete beta;
delete alpha;
beta = NULL;
alpha = NULL;
For every new there has to be one and only one delete during the execution of your application.
So it doesn't matter whether delete pointerB is called in the destructor or delete beta is called outside as you did. Because it is the same memory that is freed here! The question is if A "owns" an instance of B (and thus is responsible for freeing the memory it uses) or if A only has a reference to an instance of B (and is for example deleted when beta is still used).
BUT (as Roger already pointed out) I suggest reading the documentation to std::shared_ptr and std::unique_ptr. Here for example: http://en.cppreference.com/w/cpp/memory In most cases you can make good use of these and then you don't have to care for memory management.
It looks like objects of type A retain a pointer to a B object but don't own a B. This is fine and A's destructor shouldn't attempt to delete the B object.
Given this model, the client should ensure that the B object passed by pointer to A's constructor remains in existence throughout the lifetime of the A object. Your client code fails to do this but if you completely avoid dynamically allocating objects, achieving this is simple and natural and removes any possibility of leaking objects.
E.g.
void client()
{
B b;
A a(&b);
// do stuff
// Because we constructed `a` after we constructed `b` in this scope
// we are guarateed that `a` will be destroyed before `b` (reverse order)
// and the pointer that `a` is holding will never point to a destroyed
// object.
}
The assignment in the constructor of A: pointerB = beta; does not allocate new memory. Therefore, you do not need to de-allocate it when calling the destructor of A.
However, this behavior is risky:
B* beta = new B(); // memory for B is allocated
A alpha( B ); // local instance. A.pointerB points to beta
delete beta; // memory de-allocated
// risky part: alpha.pointerB still points to where beta was allocated
// BUT THIS MEMORY IS ALREADY FREED!
You need to carefully think about this.
Your example can be simplified to this:
struct A{};
int main()
{
A* wtf= new A;
A* omg= wtf;
delete wtf;
}
Is correct and so is this:
struct A{};
int main()
{
A* wtf= new A;
A* omg= wtf;
delete omg;
}
Deleting both is a double delete error, don't do this:
delete omg;
delete wtf;
You would be trying to deallocate the same memory both pointers are pointing at, twice!
When you allocate memory dynamically you have to release it.
When you do new B() You allocate memory for the object dynamically and then assign the address to beta which is of type B*. This is a pointer to that memory. When you do delete beta, you delete the memory that was allocated. This memory can be pointed by many pointers (like the one in your constructor )BUT you need to delete only once. But if you make attempts to use the other pointers (dereferencing etc.) you can blow your code.
Only when you do new you allocate memory. [Your code must contain equal and corresponding number of delete] which has to be released
Consider this way, you have a place for storing data and several labels pointing to the location of that place. Now if using one label you destroy the place, the other labels will still be having the location. But now its useless since the place is inexistent now.
The whole idea is, if you allocate something from heap, you should deallocate it and it should be done only once, and, you shouldn't access the memory after it is deallocated.
In order to achieve this, we usually make allocation and deallocation to be done by same component. For example, if you allocate a piece of memory in class Foo, do the deallocation there too. However, it is only a convention to make things less error-prone. As long as you are sure that the deallocation is going to happen, and happen only once, everything is fine.
Using shared_ptr or similar facilities is also a way to ensure this behavior.
Going back to your specific example, we cannot say whether you should do the deallocation in A. What I can say is, as you have delete beta done in your main() already, if you do the deallocation both in A and main() then it is a problem.
Whether you should deallocate in A or leave it to the caller depends on your design.
You have to delete it in destructor of A. There is a sample program you can test both conditions by
1. Run the program still value of b exists means you have to delete it in destructor of A.
2. Uncomment delete b line in the code and you will see b is free.
class B;
class A
{
B * b;
public:
A(B * obj)
{
b = obj;
}
~A()
{
//delete b;
}
};
class B
{
int value;
public:
B()
{
value = 10;
}
~B()
{
}
int getValue(){return value;}
};
void main()
{
B *b = new B;
A * a = new A(b);
delete a;
cout<<"B exists: "<<b->getValue();
}

Destructor for class that holds pointer to object

Lets say we have a class that holds a pointer member to another object. If I delete that pointer in the destructor I get an error (and I understand why).
My question is : is it possible to overcome that without memory leaks ?
Here is a demo of what I am doing.
class A {
public:
~A() { cout<< "~A()" <<endl; }
};
class B {
A *pA;
public:
B(A* pA) {
this->pA = pA;
}
~B() {
delete pA;
cout<<"~B()"<<endl;
}
};
int main() {
A a;
{
B b2(new A()); //deletes A, deletes B, no memory leaks
}
{
B b(&a); //deletes A, error.
}
return 0;
}
First of all that's not memory leak, but an undefined behavior, a more serious issue. An attempt is made to deallocate a memory from wrong region.
One should use delete/delete[]/free() only on corresponding new/new[]/malloc().
There is no full proof and architecture independent way, just adhere to good programming practices.
May not be perfect always, but one way is to overload new and delete and hold a std::map like data structure. Whenever new is called add the pointer to it. Upon delete you can make check if the pointer exists or not, if the allocation was of type new or new[] etc..
Definitely this will affect your performance, so you need to keep it under debug mode.
You have two objects that think they own a dynamically allocated object and try to delete it. The solution is to decide who should own the object, and to implement the correct copy/assignment behaviour with the help of the appropriate smart pointer:
Do A and B deal with dynamically allocated objects at all? There is no way of knowing this from a raw pointer, so the design has to be revised to cover one case or the other. Assuming dynamic object allocation, then
Each object owns its own copy: Implement the rule of three in A or B, and have only one of the two delete. You can use a scoped pointer to simplify memory management (boost_scoped_ptr, or std::unique_ptr).
Unique ownership: a single object owns the copy: Use std::unique_ptr. Disallow copy and assignment, allow move-copy and move-assignment
Shared ownership: Nobody/everybody owns the object. It gets deleted when nobody references it: use std::shared_ptr
You must tell B, when it owns the pointer and when it doesn't.
Add an additional flag telling when
class B {
bool owner;
A *pA;
public:
B(A* pA, bool bOwner) : owner(bOwner) {
this->pA = pA;
}
~B() {
if (owner)
delete pA;
cout<<"~B()"<<endl;
}
};
int main() {
A a;
{
B b2(new A(), true); //deletes A, destroys B, no memory leaks
}
{
B b(&a, false); //destroys B, ok.
}
return 0;
}

In C++, how to write a destructor for freeing memory of pointer to a structure?

Here's my structure A
struct A {
int a1;
int a2;
~A() { }
};
B is another structure that contains a pointer to A
struct B {
B(int b, A* a)
: b1(b), ptr2A(a)
{}
int b1;
A* ptr2A;
~B() {
delete b1;
// traverse each element pointed to by A, delete them <----
}
};
Later on I use below code
int bb1;
vector <A*> aa1;
// do some stuff
B *ptrB = new B(bb1, aa1);
I need to delete/free all the memory pointed to by ptrB. Hence I need to write correct destructor inside struct B. How do I traverse each element pointed to by A and delete them?
If you're using a C++11 compiler, just use std::shared_ptr and you don't have to worry about deletes. This is because the shared_ptr is a "smart" pointer that will automatically delete what its pointing to.
#include <memory>
struct B
{
int b1;
std::shared_ptr<A> ptr2A;
B(int b, std::shared_ptr<A> a):b1(b),ptr2A(a)({}
~B(){} //look ma! no deletes!
};
Use a shared pointer whenever you allocate something:
#include<memory>
...
{
....
std::shared_ptr<B> ptrB( new B(bb1, aa1) );
//Here is another, more readable way of doing the same thing:
//auto ptrB = std::make_shared<B>(bb1,aa1);
...
}
//no memory leaks here, because B is automatically destroyed
Here's more info on the subject of smart pointers.
I should also mention that if you don't have a C++11 compiler, you can get shared pointers from the BOOST library.
You need only to delete objects allocated by new. In this case there's no need to delete b1 as it has not been dynamically-allocated. Moreover, if you did not initialize ptr2a with dynamic memory, deleting it is undefined behavior.
So there's no need to worry about deleting As data as it will be destructed from memory along wih the instance of the class.
You've only got one pointer to A. So you only need to delete that:
~B() {
delete ptr2A;
}
Note that you can't delete b1, since it's a plain int! (The memory taken up by the variables of the structure, such as b1 and the pointer ptr2A itself (not what it points to) are destroyed automatically along with any instances of that structure.)

C++ pointer handling

Suppose I create a form using a pointer and that form contains sub item as another pointer, when I delete the form, I perform a delete operation on the main pointer, do I need to perform a delete operation on the sub pointer also or the compiler does that on its own?
If you're the one allocating memory for the pointer, yes, you need to explicitly release all memory you're allocating.
struct A
{
};
struct B
{
A* a;
B() { a = new A; }
~B();
};
B* b = new B;
delete b;
//you will have a memory leak here, since the memory pointed to by b.a
//is not released
The proper way is freeing the memory in the destructor:
struct B
{
A* a;
B() { a = new A; }
~B() { delete a; }
};
You should read up on smart pointers, they might suit your case better.
Yes, you'll normally need to delete that explicitly to avoid a memory leak. Simple rule: if you used new to allocate it, you'll need a matching delete to free it.
That said, you usually want to use something like a smart pointer that handles all this automatically.
This question hinges on the way the destructor for the form is written. For example, the form may try to call the destructor for the sub-form. If it performs this kind of cleanup then you do not need to further release the sub-form. It would be informative to know what form management system you are talking about (for example MFC).