Jump to content

  • Log In with Google      Sign In   
  • Create Account


How to check if dynamic memory is there before deleting?


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 Shaquil   Members   -  Reputation: 811

Like
0Likes
Like

Posted 28 December 2012 - 07:16 PM

I'm sorry if this question has been asked before, but I'm struggling with figuring out how to google it right. I don't know how to pose the question without an example.

 

Say I have this code:

 

 

int main(){

   int * ptr = NULL;

   int input = 0;

   cin >> input;

   if(input > 5)
      ptr = new int;

  /*Apparently this doesn't work..*/
   if(ptr)
      delete ptr;

   return 0;
}

 

That's basically the way I've been checking if a pointer has been allocated dynamic memory or not, but I've just learned that my solution is wrong. So what might be one smart way to go about it? I just made the above code off the top of my head, so please don't criticize it for stuff that's off-topic from the question. Thanks a lot.


Edited by Shaquil, 28 December 2012 - 07:18 PM.


Sponsor:

#2 Brother Bob   Moderators   -  Reputation: 7405

Like
6Likes
Like

Posted 28 December 2012 - 07:24 PM

Your solution is not wrong, but you may have misunderstood why it's not useful to check for null before deleting. It is not that your code won't work. the pointer is initially null, and if you allocate something, then the pointer is not null and it will be deleted. Likewise, if you don't allocate anything, then the pointer remains null and it won't delete it.

 

But that's not the issue. The "problem" is that calling delete on a null pointer is perfectly fine, so the if-statement is useless. Not incorrect, just useless. If ptr is null, then delete does nothing.



#3 Shaquil   Members   -  Reputation: 811

Like
0Likes
Like

Posted 28 December 2012 - 07:49 PM

Your solution is not wrong, but you may have misunderstood why it's not useful to check for null before deleting. It is not that your code won't work. the pointer is initially null, and if you allocate something, then the pointer is not null and it will be deleted. Likewise, if you don't allocate anything, then the pointer remains null and it won't delete it.

 

But that's not the issue. The "problem" is that calling delete on a null pointer is perfectly fine, so the if-statement is useless. Not incorrect, just useless. If ptr is null, then delete does nothing.

 

Oh that's probably the worst answer I could've gotten. Not because it's a bad answer, but because now I'm even more confused. Thank you for explaining that, though.



#4 Servant of the Lord   Crossbones+   -  Reputation: 14929

Like
1Likes
Like

Posted 28 December 2012 - 08:13 PM

but because now I'm even more confused.


'delete' is just a function that looks different than other functions. Inside the delete function, it does the if(ptr == NULL) check for you.

 

Deleting NULL does nothing, so no harm is done. Deleting the same (non-NULL) memory twice is bad though. Deleting memory that was never allocated is also bad.


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#5 phil_t   Crossbones+   -  Reputation: 2484

Like
0Likes
Like

Posted 28 December 2012 - 08:14 PM

Brother Bob is correct. What was it that made you think "I've just learned that my solution is wrong."?

#6 Madhed   Crossbones+   -  Reputation: 2015

Like
5Likes
Like

Posted 28 December 2012 - 08:17 PM

In c++ you can not test if a raw pointer actually points to allocated memory. You have to keep track of that yourself. I guess the problem you were experiencing was double-deleting memory. One solution is to set the pointer to null immediately after deleting it, if you plan on reusing it later.

 

However, you should also look into the standard library containers and smart pointers. (std::vector, std::list, std::shared_ptr, std::weak_ptr, etc.) They are the basics of modern, idiomatic c++ and in many cases eliminate the need to manually manage your memory.



#7 Dan Mayor   Crossbones+   -  Reputation: 1712

Like
2Likes
Like

Posted 28 December 2012 - 08:22 PM

I'll agree with Madhed on this one, you should have a basic understanding of how dynamic memory works under the hood but there's very few occasions that would call for custom memory managed systems.  The Standard Template Library or STL (std:: classes) provide a wide range of easy to use and trustworthy dynamic memory wrappers.


Digivance Game Studios Founder:

Dan Mayor - Dan@Digivance.com
 www.Digivance.com


#8 LordJulian   Members   -  Reputation: 151

Like
2Likes
Like

Posted 28 December 2012 - 09:53 PM

Wanting to delete memory and not being sure if you actually should delete it is the root of all evil. Try to impose as many rules as you can on your own code and make it as close to impossible as possible for others using your classes to do something stupid. One such an idea would be to enforce the creation and deletion of your object to stay in your own code (private constructors/destructors and friend class manager?). Anyhow, it's a tricky subject that cannot be taught in a few posts. Learn the basics of allocation/deletion very well, experiment a lot and grow wiser. At one point, you will feel confidant enough to answer your own question (and, from time to time, you will fail tongue.png, but keep it up ). You will know that you have the right implementation the moment you will KNOW that you MUST delete some memory and not wonder anymore.


Edited by LordJulian, 28 December 2012 - 09:55 PM.


#9 JiiPee   Members   -  Reputation: 135

Like
-2Likes
Like

Posted 29 December 2012 - 02:19 PM

If memory is not there, then you can't even allocate memory, otherwise if you have succesfully allocated memory with new then there is reserved memory size of the data type. I think you should perhaps think otherway around, how to ensure that there is memory before allocating or if program can't allocate memory then how to catch exceptions and what are actions to avoid useless deletions.


See my game dev blog: http://gamedev4hobby.blogspot.fi/

#10 Álvaro   Crossbones+   -  Reputation: 10640

Like
2Likes
Like

Posted 29 December 2012 - 03:07 PM

I guess the problem you were experiencing was double-deleting memory. One solution is to set the pointer to null immediately after deleting it, if you plan on reusing it later.
That's not much of a solution. We have had this controversy before in these forums, and to me it feels wrong to set the pointer to null, and it might give you a false sense of security. Double-deleting memory tends to happen when you have two different pointers to the same data and the programmer is confused about ownership. Setting pointers to null is a bit like rearranging the deck chairs on the Titanic.
However, you should also look into the standard library containers and smart pointers. (std::vector, std::list, std::shared_ptr, std::weak_ptr, etc.) They are the basics of modern, idiomatic c++ and in many cases eliminate the need to manually manage your memory.
This, with strong emphasis on std::vector.

#11 Khatharr   Crossbones+   -  Reputation: 2614

Like
0Likes
Like

Posted 29 December 2012 - 03:12 PM

If memory is not there, then you can't even allocate memory, otherwise if you have succesfully allocated memory with new then there is reserved memory size of the data type. I think you should perhaps think otherway around, how to ensure that there is memory before allocating or if program can't allocate memory then how to catch exceptions and what are actions to avoid useless deletions.

 

When he said 'is there' I think he meant 'is still allocated'. What he was really asking is if there's a way to check the status of an allocation, which for raw pointers is a 'no'. I don't think he's worried about the heap itself disappearing somewhere.


Edited by Khatharr, 29 December 2012 - 03:14 PM.

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.

#12 Madhed   Crossbones+   -  Reputation: 2015

Like
0Likes
Like

Posted 29 December 2012 - 03:21 PM

Double-deleting memory tends to happen when you have two different pointers to the same data and the programmer is confused about ownership

 

Yeah, of course. In that case nulling one of the pointers doesn't help at all. Maybe we can make a point and say that manually managing memory shall only be done if you are 100% confident in what the feck you are doing.

 

with strong emphasis on std::vector.

 

Agreed.



#13 Khatharr   Crossbones+   -  Reputation: 2614

Like
0Likes
Like

Posted 29 December 2012 - 04:03 PM

Double-deleting memory tends to happen when you have two different pointers to the same data and the programmer is confused about ownership

 

 

Yeah, of course. In that case nulling one of the pointers doesn't help at all. Maybe we can make a point and say that manually managing memory shall only be done if you are 100% confident in what the feck you are doing.

 

As well as everyone else who may mess with the allocation in question.


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.

#14 samoth   Crossbones+   -  Reputation: 4068

Like
1Likes
Like

Posted 29 December 2012 - 05:38 PM

Checking for NULL before deleting and setting a pointer to NULL after deletion is troublesome in my opinion for many reasons.

 

Not only is it useless code and needless work (C++ guarantees that deleting NULL is a no-op). Code that doesn't add value should not be written. More code means not only extra opportunities for mistakes and wasted CPU cycles, but also "noise". Your brain can do so and so many things per second, and more text means that it needs to pick up more information. Skipping over a single if is no big deal, but then again, something that is entirely useless is kind of "expensive" even when the cost is otherwise neglegible.

 

But more importantly, it is also the wrong approach. Deleting resources should be well-defined, controlled, and guaranteed (read as: exception safe). It should not be "random" or some kind of guesswork with workarounds that prevent a crash when things go wrong. If you double-delete an object, that is a programming error which needs to be corrected. This should never happen. If it happens, your program should crash, and it should crash early. If you prevent your program from crashing, you are coalescing wrong behaviour.

 

Also, the if(ptr) delete ptr; idiom can be a source of many-hours-wasted in "works fine in debugger, crashes otherwise" type of errors. When you have an uninitialized pointer and run the code in a debugger, this will "magically" work, because the debugger zero-initializes the variable.

It would of course also "magically work" without the if condition (since the standard guarantees that). However, you have a chance (depends on the quality of your allocator and/or CRT and/or debugger) to get a "deleted null pointer in line..." warning.  When there is an if(ptr) in the way, delete is never called. You've successfully eleminated the most helpful hint that would tell you what has gone wrong.

When you run the program outside the debugger, it will attempt to delete some random memory address and crash (or, if you are very unlucky... not crash, or crash sometimes, because you've incidentially gotten a valid address). So you spend hours trying to figure why it works "fine" in the debugger, but crashes otherwise.



#15 Shaquil   Members   -  Reputation: 811

Like
0Likes
Like

Posted 29 December 2012 - 06:26 PM

I guess the problem you were experiencing was double-deleting memory. One solution is to set the pointer to null immediately after deleting it, if you plan on reusing it later.
That's not much of a solution. We have had this controversy before in these forums, and to me it feels wrong to set the pointer to null, and it might give you a false sense of security. Double-deleting memory tends to happen when you have two different pointers to the same data and the programmer is confused about ownership. Setting pointers to null is a bit like rearranging the deck chairs on the Titanic

 

I don't understand what you're trying to say. Anytime anyone talks about C++ they use these weird, dramatic metaphors. How is it a false sense of security? Why is it wrong? Please explain it to me like I'm stupid.



#16 Álvaro   Crossbones+   -  Reputation: 10640

Like
2Likes
Like

Posted 29 December 2012 - 08:06 PM



I guess the problem you were experiencing was double-deleting memory. One solution is to set the pointer to null immediately after deleting it, if you plan on reusing it later.

That's not much of a solution. We have had this controversy before in these forums, and to me it feels wrong to set the pointer to null, and it might give you a false sense of security. Double-deleting memory tends to happen when you have two different pointers to the same data and the programmer is confused about ownership. Setting pointers to null is a bit like rearranging the deck chairs on the Titanic


 
I don't understand what you're trying to say. Anytime anyone talks about C++ they use these weird, dramatic metaphors. How is it a false sense of security? Why is it wrong? Please explain it to me like I'm stupid.
 



Sorry about the dramatic metaphor. The point is that you can do memory management correctly or incorrectly. If you do it correctly, you don't need to set the pointer to null after deleting it. If you do it incorrectly, setting the pointer to null after deleting it will not help things much: The only situation in which it can help is where you try to use the pointer to access the data after it has been released, because it will make the program crash consistently. On the other hand, if the problem is that you end up deleting that pointer twice, you will be masking a problem instead (I think samoth pointed this out).

If you are doing memory management incorrectly, you should do it correctly:
* Use standard containers in the vast majority of situations.
* When you have to use `new' (say, in a factory function), wrap the pointer right away in something like a unique_ptr.
* If you ever write a function that uses `new' and returns the raw pointer, make a huge comment indicating that this is the case and that the caller is now responsible for deleting it. But you should really use the unique_ptr instead.

I use C++ every day and I haven't had a memory leak in 10 years. It's not all that hard. I consider `new' as suspect as most people consider `goto', and for similar reasons: I know that in the hands of an inexperienced programmer it can lead to messes that I don't want to deal with.

#17 Servant of the Lord   Crossbones+   -  Reputation: 14929

Like
2Likes
Like

Posted 29 December 2012 - 08:42 PM

* When you have to use `new' (say, in a factory function), wrap the pointer right away in something like a unique_ptr.
Better yet, if you let smart pointers handle 'delete' for you, you might as well let them handle 'new' as well.
std::make_shared<> exists for this purpose, and though there isn't a std::make_unique<>, it is an acknowledged oversight that will be patched in to the standard later.

There are still reasons and occasions to use new and delete directly (just as there are rare occasions to use malloc() and free())... but those occasions will be few and far between.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#18 Khatharr   Crossbones+   -  Reputation: 2614

Like
0Likes
Like

Posted 29 December 2012 - 08:56 PM

I don't understand what you're trying to say. Anytime anyone talks about C++ they use these weird, dramatic metaphors. How is it a false sense of security? Why is it wrong? Please explain it to me like I'm stupid.

 

There are much better ways of handling memory management in C++ (compared to C), and those ways are important because it can be a lot harder to keep track of who has which pointer to what.

 

In other words it's not 'wrong' in the sense of not compiling and running. It's 'wrong' in the sense that someone may try to slap you if they catch you doing it.


Edited by Khatharr, 29 December 2012 - 08:57 PM.

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.

#19 Shaquil   Members   -  Reputation: 811

Like
0Likes
Like

Posted 29 December 2012 - 10:33 PM

Sorry about the dramatic metaphor. The point is that you can do memory management correctly or incorrectly. If you do it correctly, you don't need to set the pointer to null after deleting it. If you do it incorrectly, setting the pointer to null after deleting it will not help things much: The only situation in which it can help is where you try to use the pointer to access the data after it has been released, because it will make the program crash consistently. On the other hand, if the problem is that you end up deleting that pointer twice, you will be masking a problem instead (I think samoth pointed this out).

If you are doing memory management incorrectly, you should do it correctly:
* Use standard containers in the vast majority of situations.
* When you have to use `new' (say, in a factory function), wrap the pointer right away in something like a unique_ptr.
* If you ever write a function that uses `new' and returns the raw pointer, make a huge comment indicating that this is the case and that the caller is now responsible for deleting it. But you should really use the unique_ptr instead.

I use C++ every day and I haven't had a memory leak in 10 years. It's not all that hard. I consider `new' as suspect as most people consider `goto', and for similar reasons: I know that in the hands of an inexperienced programmer it can lead to messes that I don't want to deal with.

 

Thank you so much. I wish I'd known this before I started my most recent project, but at least it's a learning experience. In cases where I use new and delete, and I realize that I'm making a messy web where I'll need to know exactly what gets deleted by who, I occasionally think, "Well, I could probably just use something in STL for this instead and save the head." But then I always wonder if that's the right choice. I do, after all, have to learn what new and delete does. And I worry that using one of the STL structures like vector might be overkill.

 

I'd love to hear some opinions on these thoughts, since I've never gotten much of a chance to talk about this with anyone else before. From other posts I've read, Servant of the Lord seems really knowledgeable about this stuff as well.



#20 0r0d   Members   -  Reputation: 797

Like
0Likes
Like

Posted 29 December 2012 - 10:55 PM

Look into boost::shared_ptr and boost::weak_ptr.

 

Handling pointers to objects is inherently difficult because in many cases you'll want to pass off or store copies of those pointers.  Then you need to deal with knowing when it's safe to delete.  It's a problem of ownership.  You either have strict ownership or you have a mechanism for knowing when it's safe to delete.  If you're not that experienced then you can easily fall into traps you've set for yourself.  Using shared_ptr and weak_ptr together can help you solve the problem of ownership and get rid of the need for deletes. 






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