Skip to main content
GameDev.net gamedev.net
🔒 Locked

Class destructor in c++

Started by Dark Metamorphosis Jul 5, 2004 at 4:11 PM 8 replies 1.1k views
Original Post
Dark Metamorphosis
Dark Metamorphosis
hi every one. ok I am getting nuts, because the destructor is called twice, witch make me get an assertion error: BLOCK_HEAD_IS_VALID, any here is the example: class TEST { public: int* ptr ; TEST() ; ~TEST() ; }; TEST::TEST() { ptr = new int[10] ; } TEST::~TEST() { cout << "calling destructor..." << endl ; if (ptr) {delete ptr ; ptr = NULL; }; } TEST Function() { TEST result ; return result ; } void main() { Function() ; } the output of this example is like this: calling destructor... calling destructor... so the destructor was called twice, wich makes me get an assertion error, because I am deleting a null array (just like this: int* ptr = new int[10]; delete ptr; delete ptr;). any way, does any one know what is happening here, caus I am getting really confused here. and what shout I do to evercome this probleme?
K'-P = ME
Queasy
Queasy
maybe it's screwing up when you're deleting ptr. you should write:

delete[] ptr;

since it was allocated with 'new' as an array.

-j
Jonathan Makqueasy gamesgate 88[email=jon.mak@utoronto.ca]email[/email]
Washu
Washu
...
you are creating a local variable on the stack, then you return a copy of it.
The destructor is called twice because you have 2 objects.
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
tomek_zielinski
tomek_zielinski
You've got one pointer and many copies of it(in this example: two). So it's very very bad thing.

If you want to do it this way, your pointer need to be reference counted pointer(or another smart pointer)(www.boost.org: shared_ptr).

www.tmreality.com
tomek_zielinski
tomek_zielinski
Anonymous is right:)

There are many ways to do it - if you duplicate data in copy constructor it will take some amount of time, but it will be easier to do if you don't know anything about smart pointers.

On the other hand - smart pointers make you don't need to make copies of your data, are easy to use, but to feel comfortable using them you have to understand a nubmer of thing regarding c++ templates and classe.

You can do copying first and the try to use smart ptr.

The choice is yours;)
www.tmreality.com
snk_kid
snk_kid
As Anonymous chum has stated, when using pointers as members you need to define what it means/appriotate to copy & assign otherwise a default is provided that does a shallow copy& assignment. Also your allocating an array but using the wrong delete for it so with that in mind this how it should look like:

#include <algorithm>class TEST{public:int* ptr;int _size;//default constructorTEST(int size = 10): ptr(0), _size(size) {   ptr = new int[_size];}//copy constructorTEST(const TEST& t): ptr(0), _size(t._size) {   ptr = new[_size];   std::copy(t.ptr, (t.ptr + t._size), ptr);}//assignement operatorTEST& operator=(const TEST& t) {   if(this != &t) {        if(ptr) {           delete[] ptr;        }        _size = t._size;        ptr   = new int[_size];        std::copy(t.ptr, (t.ptr + t._size), ptr);   }   return *this;}~TEST() {  if(ptr)   delete[] ptr;}};
Chris Hare
Chris Hare
Just so you all know, this sample class implementation of delete

	static void operator delete(void* mem, size_t s)	{		cout << "In my delete" << endl;		if (mem == 0)		{			cout << "None alloc, returning!" << endl;			return;		}		else		{			cout << "Mem alloc, deleteing" << endl;			::delete mem;			return;		}	}



is similar to ::delete, so tests like

if (ptr) { delete ptr; }

are already performed safely by delete itself.

Also, AFAIK, if you check for successful allocation by testing if the pointer has a non-zero value, you should use the nothrow version of new like

int* p = new (nothrow) int;
if (p) cout << "Allright!" << endl;

because since about 1995, standard ::new only throws (AFAIK).

PS ==> Awaiting confirmation about nothrow.


DrPizza
DrPizza
Objects containing pointers should not in general have default copy constructors, because shallow copies do not provide the correct semantics.
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;} /*** drpizza@battleaxe.net ***/
SiCrane
SiCrane
Quote:
Original post by Chris Hare
because since about 1995, standard ::new only throws (AFAIK).

PS ==> Awaiting confirmation about nothrow.


Technically, it's also possible for the non-nothrow version of the non-placement ::operator new() to cause an infinite loop rather than throwing or returning. In general, you'd have to bork your new handler in order for this to happen, so this can be considered to be a non-issue. (Unless you're trying to write your own new handler.)

Unfortunately, with some compilers it's possible to change this behaviour so that the non-nothrow version of ::operator new will not throw and will instead return 0. (Commonly done if exception handling is disabled.) So in real world situations, without knowing the context of a given code snippet, it's impossible to say if checking the result of a new call is necessary or not.

That being said, IMO, it's not good coding style to do so.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.