Jump to content

  • Log In with Google      Sign In   
  • Create Account

C++ - freeing dynamic memory


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
20 replies to this topic

#1 Shayel   Members   -  Reputation: 253

Like
1Likes
Like

Posted 24 April 2013 - 08:09 AM

Hello, I was wondering about freeing the dynamic memory, when the pointer is returned by the function. Let's say I have some piece of code:

int* allocate()
{
     int* ptr=new int[10];
     return ptr;
}

int main()
{
     int* myPointer=allocate();
     delete [] myPointer;
     return 0;
}

Is this ok? I mean, is freeing the memory outside the function ok? It doesn't return exactly the same pointer, but when using "return" it creates a copy of the object, and the returns the copy.. am I correct? So myPointer points on the same place in the memory, even if it isn't "ptr".

 

Another example:

int* ptr1=NULL, ptr2=NULL, ptr3=NULL, ptr4=NULL;
ptr1=new int;
ptr2=ptr1;
ptr3=ptr2;
ptr4=ptr3;
delete ptr4;

Am I freeing ptr1-3, when freeing ptr4?



Sponsor:

#2 Brother Bob   Moderators   -  Reputation: 8197

Like
2Likes
Like

Posted 24 April 2013 - 08:18 AM

Hello, I was wondering about freeing the dynamic memory, when the pointer is returned by the function. Let's say I have some piece of code:

int* allocate()
{
     int* ptr=new int[10];
     return ptr;
}

int main()
{
     int* myPointer=allocate();
     delete [] myPointer;
     return 0;
}

Is this ok? I mean, is freeing the memory outside the function ok? It doesn't return exactly the same pointer, but when using "return" it creates a copy of the object, and the returns the copy.. am I correct? So myPointer points on the same place in the memory, even if it isn't "ptr".

It is perfectly fine. If the returned value is not the same pointer, then you are either mistaken or something is seriously wrong with your compiler. The pointer is (or should be, if it really is different for you) returned by value, so the value of myPointer is main should be the same as the value of ptr in allocate.

 

Another example:

int* ptr1=NULL, ptr2=NULL, ptr3=NULL, ptr4=NULL;
ptr1=new int;
ptr2=ptr1;
ptr3=ptr2;
ptr4=ptr3;
delete ptr4;

Am I freeing ptr1-3, when freeing ptr4?

Don't think about it as freeing a pointer, but as freeing what the pointer points to. Since all four pointers point to the same thing, then calling delete on one of the four pointers will free the object returned by new.



#3 Álvaro   Crossbones+   -  Reputation: 13318

Like
2Likes
Like

Posted 24 April 2013 - 08:46 AM

Once you are done learning how to use dynamic memory allocation and naked pointers, learn how to use standard containers (particularly std::vector) and never do it again. If you are tempted to use dynamic memory allocation and naked pointers in the future when you need polymorphism, learn about standard (in C++11) smart pointers (particularly std::unique_ptr) and continue not doing it.

Edited by Álvaro, 24 April 2013 - 08:47 AM.


#4 VladR   Members   -  Reputation: 722

Like
0Likes
Like

Posted 24 April 2013 - 09:32 AM

Generally, you want to enncapsulate the Allocation / Deallocation functionality to the class and make it as automatic as possible.

 

This means:

1. Have a C-Tor that initializes the Ptr = 0

2. Have a D-Tor that releases the memory by Ptr (you don't even have to check for Ptr == 0, since C++ standard guarantees that). This way, users do not have to worry about leaks - as soon as the class goes out of scope, the allocated memory gets deallocated automatically.

3. Have some Init/Allocate function that handles the low-level details of heap allocation

 

 

This way, the pointers are abstracted away from the users of the class. it is a very bad sign, if users of your class would have to remember to clean the heap.

 

 

As has been said above, as soon as you learn the above technique, forget about it and go for Smart Pointers, or just Standard Containers.


VladR    My 3rd person action RPG on GreenLight:    http://steamcommunity.com/sharedfiles/filedetails/?id=92951596

 


#5 NightCreature83   Crossbones+   -  Reputation: 2826

Like
0Likes
Like

Posted 24 April 2013 - 09:44 AM

The pattern you are using here however is dangerous for other users of your allocate function as they don't necessarily know you are returning a pointer to an array and thus might mistakenly call "delete myPointer". I know this is just example code but I thought I point this out as it is often something that will cause confusion down the line when dealing with a real version of this pattern.

 

In all my career there has never really been a reason to write any dynamic allocation code in the games I have written and when it is done it is usually done in manager classes that have control over the lifetime of the objects. Be aware though that console game codebases can pass a lot of naked pointers around and functions often take or return pointers. So understanding of how a pointer and memory works is a pretty important concept to understand.


Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#6 Serapth   Crossbones+   -  Reputation: 5474

Like
2Likes
Like

Posted 24 April 2013 - 12:12 PM

I recommend you read this article on C++ memory management.  I think it will clarify some of the areas you are struggling with, as well as giving you an idea of how to better manage memory.



#7 Khatharr   Crossbones+   -  Reputation: 3002

Like
2Likes
Like

Posted 24 April 2013 - 05:31 PM

This is all good advice, but do make sure that you get comfortable with raw pointers and manual memory management as well. There's all sorts of exciting trouble that you'll miss out on if you don't. (Seriously, though. These are core concepts, so get good with them.)
 
 
A pointer is a numeric value that is typically used to store a memory address. It's not the data. It just points to the data.
 
A pointer is just a number:
char* aPointer = (char*)100;
aPointer -= 50;
std::cout << "The number is " << (int)aPointer << "..." << std::endl;
//Note: Do not do this in production code or the skeleton man will eat you.
You can use a pointer to point to things on the stack:
int ary[] = {5, 6, 7};
int* aPointer = ary;
std::cout << "The array contains: " << std::endl;
std::cout << *aPointer << std::endl;
++aPointer;
std::cout << *aPointer << std::endl;
++aPointer;
std::cout << *aPointer << std::endl;
//Note: You can get fired for that too, unless you have a really good reason.
 
Or you can use it to point to dynamically allocated memory.
 
The thing to really grasp in that case is that new and delete are just functions with their own weird syntax. 'new' reserves a block of memory from the heap, and 'delete' releases a block that was previously reserved by 'new'. They're almost completely unrelated to the pointer or pointers that you use to keep track of that block during its lifetime.
 
One way to think of it is to think of memory as a set of pay lockers. 'new' puts a quarter in the slot (reserves the memory) and you write down the locker number (address) on a note-card (pointer). You can copy that number to another note-card or really do whatever you want with it. Just remember to return the locker key at the end of the day (delete).

Edited by Khatharr, 26 April 2013 - 05:49 AM.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#8 Álvaro   Crossbones+   -  Reputation: 13318

Like
1Likes
Like

Posted 25 April 2013 - 05:19 AM


int ary = {5, 6, 7};
int* aPointer = &ary;


Both of those lines are wrong. Please, check your code for accuracy before posting it. Just run it through a compiler to make sure you didn't make some mistake, and then copy and paste it here.

Edited by Álvaro, 25 April 2013 - 05:20 AM.


#9 Chad Smith   Members   -  Reputation: 1134

Like
1Likes
Like

Posted 25 April 2013 - 01:53 PM

I just wanted to give some advice from someone taking a CSCE class at a University right now (Computing Foundations 2).

1: it is very good to learn the standard containers and the smart pointers it can provide. Defintely learn and use then in your personal projects.

Though I would not suggest to just forget about raw pointers after you learn them and never use them again. Honestly I was suggested same thing when I first started learning but IMO it hindered my ability to learn the core concepts. First thig is first learn the core concepts. These teach you internally about each container and allows you I better chose which contained you need at the time.

In my university class when we were taught the basics of some algorithms in some containers and we had to go implement them, we were NOT allowed to use any of the standard containers. When we had to implement a basic linked list, we could not use the std::list. That relies on raw pointers, allocating and deallocating memory on the heap. We had to imement a basic stack, and a basic tree. Now we are implementing a Graph.

They aren't being "mean" and saying the standard library containers suck and you shouldn't use them, but they are teaching us the basics of each one, the basics of how they are done internally. This is all very important. It's important to know how to use and where to use raw pointers. Don't just forget about them and never ever use them again. The core concepts are very important.

Though yes in personal projects I would use smart pointers where I could and of course the containers in the standard library.

I just wanted to point that out. The core concepts of a pointer are very important and I wouldn't suggest that you just forget them after you learn them and never use them again.

#10 Khatharr   Crossbones+   -  Reputation: 3002

Like
0Likes
Like

Posted 26 April 2013 - 05:49 AM

int ary[] = {5, 6, 7};
int* aPointer = ary;

 

I've finished another session at school, and I have my first actual programming class starting next week, so hopefully I'll actually have time for programming again instead of writing essays about how chickens should be raised and similar oh-so-important topics that need to be discussed in order to get a programming degree.

 

I'm not incredibly optimistic, though, since the class in question is "intro to programming" with no language specified...  -.-


void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#11 LordRhys   Members   -  Reputation: 355

Like
2Likes
Like

Posted 26 April 2013 - 09:10 AM

Another example:
int* ptr1=NULL, ptr2=NULL, ptr3=NULL, ptr4=NULL;
ptr1=new int;
ptr2=ptr1;
ptr3=ptr2;
ptr4=ptr3;
delete ptr4;


Am I freeing ptr1-3, when freeing ptr4?



From what I read in C++ Primer Plus this wouldn't work since ptr2,ptr3, and ptr4 are not considered pointers but ordinary int variables, the statement would have to be:
int* ptr1 = NULL, *ptr2 = NULL, *ptr3 = Null, etc...

#12 Paradigm Shifter   Crossbones+   -  Reputation: 5374

Like
0Likes
Like

Posted 26 April 2013 - 09:50 AM

That is correct LordRhys, looks like everyone else missed that, have a cookie.


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#13 Bregma   Crossbones+   -  Reputation: 5133

Like
0Likes
Like

Posted 26 April 2013 - 10:42 AM

int* ptr1=NULL, ptr2=NULL, ptr3=NULL, ptr4=NULL;
ptr1=new int;
ptr2=ptr1;
ptr3=ptr2;
ptr4=ptr3;
delete ptr4;

Thankfully, this invalid C++ code will not compile, because it's invalid.

It's invalid because you can not assign an rvalue of type "pointer to int" to an lvalue of type "int", and because there is no overload of ::operator delete on type "int".


Stephen M. Webb
Professional Free Software Developer

#14 Álvaro   Crossbones+   -  Reputation: 13318

Like
0Likes
Like

Posted 26 April 2013 - 12:25 PM

That is correct LordRhys, looks like everyone else missed that, have a cookie.

 

Yes, when I saw the `int* blah' being used, I thought of pointing out how this is a bad idea because `int* blah, foo' declares a pointer and an int. But I didn't realize that we already had an example of that mistake.

 

If you use `int *blah' you are less likely to make this mistake. But of course the compiler will catch it the vast majority of the time.



#15 Paradigm Shifter   Crossbones+   -  Reputation: 5374

Like
0Likes
Like

Posted 26 April 2013 - 12:33 PM

Ooh, religious debate time!

 

I always use int* foo; since int* is the type. I never declare more than one pointer on a single line though.

 

But this is a religious debate, no point arguing, it's like asking which is better: Sunni or Shia. One had a big nose until she had plastic surgery and became a film star, the other became a politician and died after skiing into a tree. "I've got you babe" was a good song, however.


Edited by Paradigm Shifter, 26 April 2013 - 12:34 PM.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#16 Álvaro   Crossbones+   -  Reputation: 13318

Like
0Likes
Like

Posted 26 April 2013 - 01:00 PM

Ooh, religious debate time!

 

Sure, I haven't engaged in any of those in a while. :)

 

 

I always use int* foo; since int* is the type.

 

And I guess you would like to declare arrays as `int[8] a', since `int[8]' is the type. Unfortunately, declarations in C/C++ are not always as simple as `<type> <variable_name>'.



#17 Paradigm Shifter   Crossbones+   -  Reputation: 5374

Like
0Likes
Like

Posted 26 April 2013 - 01:05 PM

Like I said, I'm not going to argue. I just wanted to post my poor Sonny & Cher joke.

 

Note both Java and C# use int[] foo; to declare arrays, much more sensible.

 

And in C#

 

int* foo, bar;

 

actually does declare 2 pointers to int. Confusing (for C/C++ programmers), but consistent.

 

There's a lot of things I'm sure they would have done differently had C been invented later on (I'm looking at you, precendence of logical operators).


Edited by Paradigm Shifter, 26 April 2013 - 01:23 PM.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#18 Brother Bob   Moderators   -  Reputation: 8197

Like
0Likes
Like

Posted 26 April 2013 - 01:33 PM

And in C#

 

int* foo, bar;

 

actually does declare 2 pointers to int. Confusing (for C/C++ programmers), but consistent.

If you need some consistency: given int *foo, bar; then both *foo and bar are of type int.



#19 Paradigm Shifter   Crossbones+   -  Reputation: 5374

Like
0Likes
Like

Posted 26 April 2013 - 01:43 PM

I suppose. Who is better though, Sonny or Cher?

 

At least we can all agree a holy war should be declared (or defined) upon people who do this

 

int * foo, bar;


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#20 Álvaro   Crossbones+   -  Reputation: 13318

Like
0Likes
Like

Posted 26 April 2013 - 02:18 PM

At least we can all agree a holy war should be declared (or defined) upon people who do this

 

int * foo, bar;

 

Splitters!






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS