class CCharacter
{
protected:
CMakePolygon* p_tex;
CLoadTextureClass* t_tex;
int status;
public:
CCharacter(void);
virtual ~CCharacter(void){CleanUp();}
virtual void Init();
virtual void Draw();
virtual void Main();
virtual void CleanUp(){delete p_tex; delete t_tex;}
void SetStatus(int n){status = n;}
};
class CLoading: public CCharacter
{
private:
int FPS;
int round;
public:
CLoading(void);
~CLoading(void){CleanUp();}
void Init();
void Main();
void Animation();
};
the program works but when I close the program I got Access Violation: 0xC0000005: on CCharacter::CleanUp function What did I do wrong?
🔒 Locked
HelP! (Access Violation ) delete pointer
Advertisement
Original Post
I have 2 classes , one is base class and the another one is derive class.
CleanUp is being called twice.... once in the inherited destructor and in the base destructor... So the pointers are being deleted twice, hence the access violation... You can take it out of one of the destructor's or make the pointers null after you delete them... that way it won't matter if you call delete on them again...
Quote:
Original post by Psycrosis
CleanUp is being called twice.... once in the inherited destructor and in the base destructor... So the pointers are being deleted twice, hence the access violation... You can take it out of one of the destructor's or make the pointers null after you delete them... that way it won't matter if you call delete on them again...
Thanks for you advice.
but I don't understand what you mean?
do you mean? I should delete one destructor like no destrutor in derived class?
I delete destrutor in derived class(CLoading class) but it still got the problem
Quote:
Original post by fantasyme Quote:
Original post by Psycrosis
CleanUp is being called twice.... once in the inherited destructor and in the base destructor... So the pointers are being deleted twice, hence the access violation... You can take it out of one of the destructor's or make the pointers null after you delete them... that way it won't matter if you call delete on them again...
Thanks for you advice.
but I don't understand what you mean?
do you mean? I should delete one destructor like no destrutor in derived class?
I delete destrutor in derived class(CLoading class) but it still got the problem
Instead of:
virtual void CleanUp(){delete p_tex; delete t_tex;}
You should do:
virtual void CleanUp(){delete p_tex; p_tex=NULL; delete t_tex; t_tex=NULL;}
Otherwise you can end up calling delete p_tex when it's already been deleted - calling delete on a NULL pointer is perfectly valid, and will do nothing.
When you have a virtual destructor in a base class it is called when the derived class is deleted or goes out of scope. When that happens the function CleanUp() is being called twice, hence pointers being deleted twice. What I am saying is the call to the CleanUp function only needs to be done in either the base or inherited destructor but not both. You should null out your pointers too as it is good coding practice. What you may have intended is a seperate cleanup for each destructor, for that you MUST override the CleanUp function in the inherited class or the base CleanUp will be called twice.
Here's an example..
class CCharacter
{
protected:
CMakePolygon* p_tex;
CLoadTextureClass* t_tex;
int status;
public:
CCharacter(void);
virtual ~CCharacter(void){CleanUp();}
virtual void Init();
virtual void Draw();
virtual void Main();
virtual void CleanUp(){delete p_tex; delete t_tex;}
void SetStatus(int n){status = n;}
};
class CLoading: public CCharacter
{
private:
int FPS;
int round;
public:
CLoading(void);
~CLoading(void){CleanUp();}
void Init();
void Main();
void Animation();
// Add this!
virtual void CleanUp(){}
};
[Edited by - Psycrosis on May 28, 2010 8:05:10 AM]
Here's an example..
class CCharacter
{
protected:
CMakePolygon* p_tex;
CLoadTextureClass* t_tex;
int status;
public:
CCharacter(void);
virtual ~CCharacter(void){CleanUp();}
virtual void Init();
virtual void Draw();
virtual void Main();
virtual void CleanUp(){delete p_tex; delete t_tex;}
void SetStatus(int n){status = n;}
};
class CLoading: public CCharacter
{
private:
int FPS;
int round;
public:
CLoading(void);
~CLoading(void){CleanUp();}
void Init();
void Main();
void Animation();
// Add this!
virtual void CleanUp(){}
};
[Edited by - Psycrosis on May 28, 2010 8:05:10 AM]
Psycrosis: True
fantasyme: You also need to be very careful when calling virtual functions inside a destructor as this might not do what you expect it to do.
fantasyme: You also need to be very careful when calling virtual functions inside a destructor as this might not do what you expect it to do.
Quote:
Original post by Evil Steve Quote:
Original post by fantasyme Quote:
Original post by Psycrosis
CleanUp is being called twice.... once in the inherited destructor and in the base destructor... So the pointers are being deleted twice, hence the access violation... You can take it out of one of the destructor's or make the pointers null after you delete them... that way it won't matter if you call delete on them again...
Thanks for you advice.
but I don't understand what you mean?
do you mean? I should delete one destructor like no destrutor in derived class?
I delete destrutor in derived class(CLoading class) but it still got the problem
Instead of:
virtual void CleanUp(){delete p_tex; delete t_tex;}
You should do:
virtual void CleanUp(){delete p_tex; p_tex=NULL; delete t_tex; t_tex=NULL;}
Otherwise you can end up calling delete p_tex when it's already been deleted - calling delete on a NULL pointer is perfectly valid, and will do nothing.
thanks for your help,
but I still got error.
Unhandled exception at 0x0018355e in RenewOracle.exe: 0xC0000005: Access violation reading location 0xcccccccc.
I did as you advise.
the problem is still delete p_tex;
Quote:That means that the pointer was never initialised. In your constructor, you should be initialising all your pointers to NULL.
Original post by fantasyme
but I still got error.
Unhandled exception at 0x0018355e in RenewOracle.exe: 0xC0000005: Access violation reading location 0xcccccccc.
Or, as SiCrane said - use a smart pointer class so you don't have to worry about this sort of thing.
Quote:
Original post by Evil Steve Quote:That means that the pointer was never initialised. In your constructor, you should be initialising all your pointers to NULL.
Original post by fantasyme
but I still got error.
Unhandled exception at 0x0018355e in RenewOracle.exe: 0xC0000005: Access violation reading location 0xcccccccc.
Or, as SiCrane said - use a smart pointer class so you don't have to worry about this sort of thing.
ok, I put p_tex and t_tex = NULL in constructor
and I got error :: Debug Assertion Failed
Expression BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
and what is smart pointer class that you mention?
Fantasyme,
The simplest solution to this problem is simply to take out CLoading's call to Cleanup():
class CLoading: public CCharacter
{
private:
...
public:
CLoading(void);
virtual ~CLoading(void){}
...
};
You don't need to call Cleanup in CLoading since the base CCharacter destructor calls it.
But also, ideally you should address the following:
1) Why is Cleanup public?
2) And why don't you set the pointers to Null after delete? Or...
3) Why don't you reinitialize another set of objects in Cleanup?
4) Instead of Cleanup, you could have a public method called CleanupAndInit that not only deletes, but reinitializes memory for p_tex and t_tex. Then, in your CCharacter destructor, simply delte p_tex and t_tex directly. Your new CCharacter class would look something like this:
class CCharacter
{
protected:
CMakePolygon* p_tex;
CLoadTextureClass* t_tex;
...
public:
CCharacter(void) { p_tex = NULL; t_tex = NULL; }
virtual ~CCharacter(void){delete p_tex; delete t_tex;}
virtual void CleanUpAndInit() {
if(p_tex != NULL) delete p_tex;
if(t_tex != NULL) delete t_tex;
p_tex = new CMakePolygon();
t_tex = new CLoadTextrueClass();
...
}
...
...
};
The simplest solution to this problem is simply to take out CLoading's call to Cleanup():
class CLoading: public CCharacter
{
private:
...
public:
CLoading(void);
virtual ~CLoading(void){}
...
};
You don't need to call Cleanup in CLoading since the base CCharacter destructor calls it.
But also, ideally you should address the following:
1) Why is Cleanup public?
2) And why don't you set the pointers to Null after delete? Or...
3) Why don't you reinitialize another set of objects in Cleanup?
4) Instead of Cleanup, you could have a public method called CleanupAndInit that not only deletes, but reinitializes memory for p_tex and t_tex. Then, in your CCharacter destructor, simply delte p_tex and t_tex directly. Your new CCharacter class would look something like this:
class CCharacter
{
protected:
CMakePolygon* p_tex;
CLoadTextureClass* t_tex;
...
public:
CCharacter(void) { p_tex = NULL; t_tex = NULL; }
virtual ~CCharacter(void){delete p_tex; delete t_tex;}
virtual void CleanUpAndInit() {
if(p_tex != NULL) delete p_tex;
if(t_tex != NULL) delete t_tex;
p_tex = new CMakePolygon();
t_tex = new CLoadTextrueClass();
...
}
...
...
};
There are several things you should learn, given what you've posted in the following snippet of code:
(void) is an old C throwback. In C++, just use ()
Constructor initialisation lists are the perferred way to initialised member variables:
CleanUpAndInit is not exception safe. The better way to do the above is to use the copy-and-swap idiom.
Use [code]code goes here[/code] or [source]code goes here[/source] tags when posting code. This ensures that indentation is retained.
fantasyme: When you have a class where the following compiles but causes, or would cause, a problem at run-time, then in my book are duty-bound to either fix it, or prevent copying:
Quote:
Original post by shobogenzo
CCharacter(void) { p_tex = NULL; t_tex = NULL; }
virtual ~CCharacter(void){delete p_tex; delete t_tex;}
virtual void CleanUpAndInit() {
if(p_tex != NULL) delete p_tex;
if(t_tex != NULL) delete t_tex;
p_tex = new CMakePolygon();
t_tex = new CLoadTextrueClass();
...
}<!--QUOTE-->
(void) is an old C throwback. In C++, just use ()
Constructor initialisation lists are the perferred way to initialised member variables:
CCharacter() : p_tex(NULL), t_tex(NULL) {}Don't check for a pointer being NULL before calling delete. It is completely normal and safe to do "delete NULL;".CleanUpAndInit is not exception safe. The better way to do the above is to use the copy-and-swap idiom.
Use [code]code goes here[/code] or [source]code goes here[/source] tags when posting code. This ensures that indentation is retained.
fantasyme: When you have a class where the following compiles but causes, or would cause, a problem at run-time, then in my book are duty-bound to either fix it, or prevent copying:
{ MyClass a; MyClass b = a; a = b;}The later is done as follows... Note the private section:class MyClass { public: OtherClass *somePointer; // constructor, destructor, other methods, etc private: MyClass(const MyClass &); MyClass& operator=(const MyClass &);}Quote:
Original post by shobogenzo
Fantasyme,
The simplest solution to this problem is simply to take out CLoading's call to Cleanup():
class CLoading: public CCharacter
{
private:
...
public:
CLoading(void);
virtual ~CLoading(void){}
...
};
You don't need to call Cleanup in CLoading since the base CCharacter destructor calls it.
But also, ideally you should address the following:
1) Why is Cleanup public?
2) And why don't you set the pointers to Null after delete? Or...
3) Why don't you reinitialize another set of objects in Cleanup?
4) Instead of Cleanup, you could have a public method called CleanupAndInit that not only deletes, but reinitializes memory for p_tex and t_tex. Then, in your CCharacter destructor, simply delte p_tex and t_tex directly. Your new CCharacter class would look something like this:
class CCharacter
{
protected:
CMakePolygon* p_tex;
CLoadTextureClass* t_tex;
...
public:
CCharacter(void) { p_tex = NULL; t_tex = NULL; }
virtual ~CCharacter(void){delete p_tex; delete t_tex;}
virtual void CleanUpAndInit() {
if(p_tex != NULL) delete p_tex;
if(t_tex != NULL) delete t_tex;
p_tex = new CMakePolygon();
t_tex = new CLoadTextrueClass();
...
}
...
...
};
thank to you and everyone.
It is ok now.
It is good to know about this.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement