delete [] question (SOLVED)

Started by
10 comments, last by Daaark 18 years, 10 months ago
What value does a variable get set too after you use the delete operator on it? I've been using this, for awhile, but it started bombing on me when some of my destructors were running at app exit. I know you are not supposed to delete stuff twice, but how do you check?

//This stuff would have already been nuked via my Kill() member function
//I keep stuff like this, simply as a backup.
c_model::~c_model()
{
    //delete the model data if it hasn't already happened
    if (m_vtx != NULL) delete [] m_vtx;
    if (m_nrm != NULL) delete [] m_nrm;
    if (m_uvw != NULL) delete [] m_uvw;
    if (m_tri != NULL) delete [] m_tri;
        
    return;
}

[Edited by - Vampyre_Dark on June 21, 2005 8:19:41 AM]
Advertisement
delete[] does not affect the value of a pointer variable; the pointer retains is previous value, but the memory it points to is not valid any more, so you should not dereference it. You can manually set it to 0 if you like.

Mark
Quote:Original post by Vampyre_Dark
What value does a variable get set too after you use the delete operator on it?


It is undefined. From your code snippet, you seem to be assuming it will get set to 0. It is not the case: you would have to do that yourself. Note, however, that you do not have to guard against deleting NULL pointers - it's a no-op.

Quote:I know you are not supposed to delete stuff twice, but how do you check?


After the fact, you can't. Set the pointer to 0 yourself when you've deleted the object if you're afraid you might delete it twice.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
delete doesn't set it to anything. The value of the pointer will still be the same, just the memory it points to doesn't belong to you any more. Calling delete on it a second time will cause a crash.

Set your pointers to 0 (or NULL) after you've deleted them, then it's easy to check whether they're valid or not.

EDIT: heh, beaten twice.
You take responsibility for checking, either by ensuring that each new'ed pointer is only owned by one class, or by always duplicating pointed-to data on copy, or by keeping a reference count, or some other scheme. Without more information about your design I can't say what would be best for your situation, but I suspect either a single owner of the data, with other objects using references to that data, or a boost::shared_ptr to a vector:
class ModelData{	// members	std::vector< gl::Vector > vertices_;	// etc.};std::map< std::string, ModelData > models;class Model{	// members	ModelData const & model_;};

or
class Model{	// members	boost::shared_ptr< std::vector< gl::Vector > > vertices_; // really ought to typedef this	// etc};

For the first you are responsible for adding models to the models map the first time they are needed and removing the entry from models when a specific model is not longer needed. For the second you are responsible for creating new vectors for the data each time a new model is created, but that model can then be copied to your hearts content. The second method will also handle deallocation for you when the Model is destructed.

By the way, there is no need to check for null before delete([])ing. delete([])ing a null pointer is defined to be a noop by the standard.

Enigma
It tend to write code like that as

    delete [] m_vtx, _vtx = 0;    delete [] m_nrm, _nrm = 0;    delete [] m_uvw, _uvw = 0;    delete [] m_tri, _tri = 0;


so the pointers are null after the delete.
---CyberbrineDreamsSuspected implementation of the Windows idle loop: void idle_loop() { *((char*)rand()) = 0; }
Quote:Original post by Fruny
Note, however, that you do not have to guard against deleting NULL pointers - it's a no-op.
I read somewhere in the last few days that you should NEVER delete stuff twice, and it could be disasterous. [lol] However, I have no clue where that was. Could have been MSDN or somewhere else. It was some official documentation, I remember that much.

Removing the extra delete in my deconstructors stopped the crashes. I'll start manually setting my stuff to NULL from now on.

Quote:You take responsibility for checking, either by ensuring that each new'ed pointer is only owned by one class, or by always duplicating pointed-to data on copy, or by keeping a reference count, or some other scheme. Without more information about your design I can't say what would be best for your situation, but I suspect either a single owner of the data, with other objects using references to that data, or a boost::shared_ptr to a vector:
???I'm doing nothing near that complicated. [lol] Just trying to clean up properly. The c_models aren't apart of any hierarchy or anything. I just load 'em and draw 'em as needed.

Quote:Original post by MauMan
It tend to write code like that as

*** Source Snippet Removed ***

so the pointers are null after the delete.
Nice.
If your models are not part of a hierarchy then what is the problem? Allocate in the constructor and deallocate in the destructor. Better yet, use vectors and don't worry about the deallocation.
Quote:Original post by Vampyre_Dark
Quote:Original post by MauMan
It tend to write code like that as
delete [] m_vtx, _vtx = 0;delete [] m_nrm, _nrm = 0;delete [] m_uvw, _uvw = 0;delete [] m_tri, _tri = 0;

so the pointers are null after the delete.

Nice.

Not all that nice. It will save you in a few situations, but not many. Wrapped pointers are much safer:
#include <vector>#include <boost/shared_ptr.hpp>class SetToNull{	public:		SetToNull()			:			array_(new int[12])		{		}		~SetToNull()		{			delete[] array_;			array_ = 0;		}	private:		int * array_;};class UseWrapped{	public:		UseWrapped()			:			array_(new std::vector< int >(12))		{		}	private:		boost::shared_ptr< std::vector< int > > array_;};int main(){	{		SetToNull stn1;		SetToNull stn2(stn1);	} // BANG! double deletion	{		UseWrapped uw1;		UseWrapped uw2(uw1);	} // OK.}


Enigma
If you have zeroed the pointer, you can safely call delete/delete[] as many times as you want. But like other have said before, the actual return from delete/delete[] is undefined. Which means the results of calling delete/delete[] a second time without zeroing it is also undefined.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

Quote:Original post by Enigma
what is the problem?
(not to be rude, I appreciate what you posted for me) It has nothing to do with what I asked. I didn't ask about boost, or vectors, or smart pointers. I asked about delete keyword specific functionality. [embarrass]

Thanks to all who answered, it's solved, and no more crashes on exit.

This topic is closed to new replies.

Advertisement