Destructor not being invoked?

Started by
7 comments, last by SnT2k 18 years, 10 months ago

Anyone know why the destructor doesnt get called?  I thought when the reference 
count was 0 it automatically gets called.  When I take out pc2.printInfo() 
(last line of call() ), it calls the destructor.  Anyone know why that happens?


#include <iostream>
using namespace std;

class PointerClass{
      public:
             PointerClass(int val, char *str){
             ip = new int(val);
             cs = str;          
             }
             void blankVal(){ *ip = 0; cs = '\0'; }
             void printInfo(){ cout << "*ip = " << *ip << endl << "cs = " << cs << endl; }
             ~PointerClass(){
                             cout << "deleting ip " << endl;
                             delete ip;
             }
             
             PointerClass(const PointerClass &);
             private:             
             int *ip;
             char *cs;             
};

inline PointerClass::PointerClass(const PointerClass &pc){
       ip = new int(*(pc.ip));
       cs = (pc.cs);       
}
void call();
int main(){
    
   call();
    
    
    
}

void call(){
    PointerClass pc(50,"Hello");
    pc.printInfo();
    PointerClass pc2(pc);
    pc2.printInfo();
    pc2.blankVal();
    pc.printInfo();
    pc2.printInfo();
}
Advertisement
I'm surprised the thing doesn't just crash. When you run blankVal on pc2, you have the following line:

cs = '\0';

This is setting the value of cs to 0, ie, it is now invalid. Later on in printInfo, you're trying to output the contents of that string, which should give you an access violation. There are quite a few pitfalls with the way you're handling this string. I'd suggest you look at std::string, or some other string class to handle this.

Quote:I thought when the reference count was 0 it automatically gets called.

No. C++ doesn't have automatic garbage collection. In this case, the destructor will be called automatically when that object goes out of scope (IE, when call returns), if that's what you meant. If you allocate memory off the heap however, using the new keyword, it will remain allocated until you use delete to free it. If you loose all references to it (ie, the reference count is 0), it will still not be destroyed. It will remain allocated until your program terminates.
Quote:Original post by Nemesis2k2
I'm surprised the thing doesn't just crash. When you run blankVal on pc2, you have the following line:

cs = '\0';

This is setting the value of cs to 0, ie, it is now invalid. Later on in printInfo, you're trying to output the contents of that string, which should give you an access violation. There are quite a few pitfalls with the way you're handling this string. I'd suggest you look at std::string, or some other string class to handle this.

Quote:I thought when the reference count was 0 it automatically gets called.

No. C++ doesn't have automatic garbage collection. In this case, the destructor will be called automatically when that object goes out of scope (IE, when call returns), if that's what you meant. If you allocate memory off the heap however, using the new keyword, it will remain allocated until you use delete to free it. If you loose all references to it (ie, the reference count is 0), it will still not be destroyed. It will remain allocated until your program terminates.


Why is it an access violation?

My question was about why the destructor wasn't being called, if I take out the last line in call then it calls the destructor, if it stays in call(), the destructor isn't invoked.

When it leaves scope, there are no references, so it should be called, it isn't referenced in main either. When call() is done, I dont see why the destructor isnt called.
Because cs is a null pointer, '\0'==0==NULL. Did you mean "\0", or just ""?
Quote:Why is it an access violation?

cs is a pointer to a character. When you set its location in the constructor, you are directing that pointer to the location of an already existing character, in this case, the start of the constant string "Hello". When you set it to 0 in the blackVal() function, you are directing that pointer to the location 0. You don't have a character, or a string, or any other kind of data that belongs to your program at location 0. When you try and read or write to this location, it will cause an access violation, as your program doesn't have the rights to access that area.

Quote:My question was about why the destructor wasn't being called, if I take out the last line in call then it calls the destructor, if it stays in call(), the destructor isn't invoked.

What IDE are you using? In Visual Studio, that function won't even return. The whole program will crash with an access violation as soon as you try and print the string cs is pointing to. Any problems you're having are undoubtedly related to this problem (hence why they disappear when you remove that function call).

Quote:When it leaves scope, there are no references, so it should be called, it isn't referenced in main either. When call() is done, I dont see why the destructor isnt called.

It isn't a matter of whether or not there are any references to it. Even if there were references to it somewhere, the destructor would still be called. It's a local variable,and it's going out of scope, therefore it will be destroyed. The fact that it's not is related to the problem above I'm sure.


I strongly suggest you read up on some fundamentals of C++, specifically pointers and scope rules.
From what I read, whenever the reference count is 0(an object going out of scope decrements the reference count), the destructor is called. Its right last time I checked btw.

I didnt know nulling an object would screw up a program, in java it just prints out the word null if it doesnt contain valid data. I use G++ and wasn't getting any access violations or anything. But yeah that solves it, it obviously got some error and just exited the function blocks since my print statements werent working.
Nemesis2k is right. There is no reference count in C++ (unless you use Managed C++). There is in Java, but this isn't Java. You have to clean up after yourself.

delete ip; when you're done with it.

Of course, if you didn't use new to allocate memory for the object, but created it on the stack, it will get deleted when it goes out of scope.

PointerClass *pg = NULL;void SomeFunction (){    PointerClass *p1 = new PointerClass (5, "foo");    PointerClass p2 (24, "bar");    pg = &p2;    //p1 was allocated using new and must be deleted    delete p1;    /*        p2 was created on the stack and is destroyed automatically.        pg is therefore now INVALID. C++ doesn't care about p2 still being        referenced!    */}


Find a tutorial on C++ memory management. It is quite different from Java. (Personally, I found Java's method far less intuitive, but maybe that's just me).
Kippesoep
i dont normally use new on built in data types, but wanted to test out copy constructors, thanks for the advice anyway
I'll try to answer your question...
Are you sure the destructor isn't invoked? Because from the looks of your destructor, it just prints a line, calls on the delete operator and exits. So, if you didn't put cin.get() or something similar to that (or you could step throught the program), you won't see anything (probably just a flash of the console or something).

Otherwise, nothing else seems wrong with the way the destructor is constructed (save the previous comments).

{Edit} as a follow up... don't try to print a null pointer, instead do something like this:
			 void printInfo(){ 				 cout << "*ip = ";				 if ( ip )					 cout << ip;				 else					 cout << "NULL";				 cout << endl; 					cout << "cs = " << cs << endl;			 }


and instead of assigning cs to '\0' (a character literal), assign it to "\0" (a string literal) which will make it point to a string containing a null terminator instead of making it point to 0...

[Edited by - SnT2k on June 6, 2005 4:36:00 AM]

This topic is closed to new replies.

Advertisement