Followers 0

C++ - freeing dynamic memory

20 posts in this topic

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?

1

Share on other sites

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.

2

Share on other sites
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
2

Share on other sites

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.

0

Share on other sites

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.

0

Share on other sites

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.

2

Share on other sites
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
2

Share on other sites

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
1

Share on other sites
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.
1

Share on other sites

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...  -.-

0

Share on other sites
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...
2

Share on other sites

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

0

Share on other sites

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".

0

Share on other sites

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.

0

Share on other sites

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.

0

Share on other sites

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>'.

0

Share on other sites

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).

0

Share on other sites

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.

0

Share on other sites

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;

0

Share on other sites

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

int * foo, bar;

Splitters!

0

Share on other sites

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...

Aye. Although if we ignore that then the answer is still no:

You don't delete pointers. You delete allocations.

Also:

[attachment=15341:pointing-to-god-1.jpg]

0

Create an account

Register a new account