• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 231
  • Last Modified:

Memory allocation (properly deleting a structure)

What would be the proper way to delete a structure?

I hear that if you are not careful in C++, you can delete a pointer to a variable and not the variable itself, which might lead to memory leaks and problems.

Have a look at the code snippet please.

1) IIs way #1 enough to properly clean the memory, or should I delete the individual variables first before deleting the structure?
2) How does destructors come into play with this, how do I use them... ~Test(). On this question I might be confusing structures with classes, or destructors with memory cleanup?

#include <cstdlib>
#include <iostream>
 
using namespace std;
 
	struct Test { 
	  char* data; 
	  int index; 
	  Test* nextStruct; 
	}; 
 
int main(int argc, char *argv[])
{
 
 	Test *x4 = new Test;
 	x4->data = "test";
 	x4->index = 0;
 	x4->nextStruct = NULL;
 
// delete variables, way #1
	delete x4;
 
// delete variables, way #2
	delete x4->data;
	delete x4->index;
	delete x4->nextStruct;
	delete x4;
}

Open in new window

0
codeQuantum
Asked:
codeQuantum
  • 8
  • 7
6 Solutions
 
jkrCommented:
The proper way in your example would be a plain

delete x4;

Deleting the variables inside the struct would only make sense if you allocated them via 'new' also. 'index' isn't even a pointer and 'data' a string literal that cannot be deleted. 'nextStruct', being NULL in your example would cause no harm, yet I am not sure if you really want to delete it...
0
 
codeQuantumAuthor Commented:
True, it did not compile. I had to change :

delete x4->index;
for
delete &x4->index;

I did not get an error on data. What is the problem?

This code is just an example. In my real code i need to create structures dynamically (a random number of structs with random values) and I need to write a function that does the cleanup after and frees the memory.
0
 
codeQuantumAuthor Commented:
Could you also clear my confusion about destructors with an explanation?

In other words, should I use a normal function for memory cleanup, or is it better to use a destructor ~Test() with the struct? an example would be helpful.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
jkrCommented:
The problem is that the struct members are not holding any memory that has been allocated via 'new' - thus 'delete' will fail at run-time, causing your program to terminate abnormally. There is no need to 'delete' the members unless the memory was allocated dynamically also. Calling 'delete' on the enclosing struct will do the job and take care of them. The situation would be different if you allocated 'data' differently, e.g. in the following
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
        struct Test { 
          char* data; 
          int index; 
          Test* nextStruct; 
        }; 
 
int main(int argc, char *argv[])
{
 
        Test *x4 = new Test;
        x4->data = new char[42];
        x4->index = 0;
        x4->nextStruct = NULL;
 
        delete x4->data; // dispose the member...
        delete x4; // ... then the struct
}

Open in new window

0
 
jkrCommented:
>>is it better to use a destructor ~Test() with the struct?

That would be a better idea. Yet the restriction to only 'delete' memory that was allocated using 'new' still applies. You could do that ina constructor, e.g.
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
        struct Test { 
 
          Test() {
 
            data = new char[42];
          }
 
          ~Test() {
 
            delete [] data;
          }
 
          char* data; 
          int index; 
          Test* nextStruct; 
        }; 
 
int main(int argc, char *argv[])
{
 
        Test *x4 = new Test;
        x4->index = 0;
        x4->nextStruct = NULL;
 
        delete x4; // ... then the struct
}

Open in new window

0
 
codeQuantumAuthor Commented:
Why did you declare a destructor, then still used //delete x4; at the end?

Or does delete trigger the destructor automatically?

(I am a beginner in C++)
0
 
jkrCommented:
Well, the destructor is invoked when 'delete' is called for dynamically allocated structures, not automatically. That wit will happen only when you declare the variable as a 'regular' one, not as a pointer and being created via 'new'.
0
 
jkrCommented:
BTW, see also http://www.cplusplus.com/doc/tutorial/dynamic.html ("Dynamic Memory")
0
 
codeQuantumAuthor Commented:
hahaha... I did not really understand your last post and I was reading that article just now. (before you posted the link.)

So if I am getting this right : destructors are not meant to be called manually like other functions but they are triggered by delete. For that to happen, I need to use new on the variables inside the structure (or is it the structure itself that should be dynamically allocated?) and those variables should not be pointers like nextStruct in my example.

Is that correct?
0
 
codeQuantumAuthor Commented:
Is there a function in C++ that let us test if a variable has been dynamically allocated or not?

I want to modify my destructor with conditional statements before the delete so it works in all cases.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Is there a function in C++ that let us test if a variable has been dynamically allocated or not?
Short answer, no.

You might find this a useful read...
"Requiring or prohibiting heap-based objects"
http://www.ishiboo.com/~nirva/c++/eff/MEC/MI27_FR.HTM
0
 
jkrCommented:
>>destructors are not meant to be called manually like other functions but they
>>are triggered by delete

Either by a 'delete' or by the object going out of scope.

BTW, since you are allocating the variables via 'new', you *do* know which ones were allocated dynamically - you wrote the code that does it...
0
 
codeQuantumAuthor Commented:
You mean I should make the constructor use new for all variables to make sure?

But what if I use x4->data... That would not go through the constructor and I will have a problem?
0
 
jkrCommented:
No, only for the ones that need to be dynamically allocated. Alternatively, initialize them to NULL and later delete them in the destructor if they are changed, e.g.
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
        struct Test { 
 
          Test() {
 
            data = NULL
          }
 
          ~Test() {
 
            if (data != NULL) delete [] data;
          }
 
          char* data; 
          int index; 
          Test* nextStruct; 
        }; 
 
int main(int argc, char *argv[])
{
 
        Test *x4 = new Test;
        x4->index = 0;
        x4->data = new char[42];
        x4->nextStruct = NULL;
 
        delete x4; 
}

Open in new window

0
 
codeQuantumAuthor Commented:
Ok I think I am getting there. 2 details :

1) Since you only used the string in the constructor, does that mean integers and pointers don`t need to be dynamically allocated?
2) And what if I do something like :

Test *x3 = new Test{"string", 4, x2};

It won`t be affected by the constructor giving NUL values, right?

(by the way I doubled the points for this question)
0
 
codeQuantumAuthor Commented:
Worked out the details Thanks for your invaluable help, jkr!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now