What can this curious combination of "while" and "delete" mean?

After reviewing a rather old project, I found the following curious piece of code (only selected code):

class CCuriousClass { ~CCuriousClass(); CSomeType* object; }; CCuriousClass::~CCuriousClass() { while( object != NULL ) { delete object; } } 

Am I in control or is this a simple way to undefined behavior?

What I see here is that if object is a null pointer at the point CCuriousClass::~CCuriousClass() being called, everything will be fine - no action is taken, but if object not null, it will be an infinite loop with undefined behavior inside.

This is most likely a mistake or some kind of smart design, which I do not understand?

+4
source share
11 answers

Since your question seems to imply "What could someone have in mind with this?" not "Why is this a fantastic idea?" I suggest the following:

 class CSomeType { CCuriousClass* m_plistentry; CSomeType* m_pnext; ~CSomeType() { m_plistentry->object = m_pnext; } }; 

The main idea could be that the owner points to a list of the list, and the list can only be deleted by head. If the head is removed, it sets the parent pointer to the new list header. If the parent is destroyed, it destroys each item in the list.

Now this is clearly a code from the crazy city.

+6
source

It looks like an error.

+13
source

Perhaps some crazy CSomeType implemented CSomeType with a link back to his own CCuriousClass , and his destructor sometimes creates a replacement. Something like that:

 class CSomeType { public: explicit CSomeType(CCuriousClass &parent) : parent(parent) {} ~CSomeType() { parent.object = respawn() ? new CSomeType(parent) : 0; } private: CCuriousClass &parent; }; 

I do not suggest anyone ever write such twisted logic. It probably still gives undefined behavior, as I believe delete allowed to change the pointer. But this may explain why someone might think that this code might be valid.

On the other hand, this is probably just an error caused by a misunderstanding of how delete works.

+9
source

As you say, this is a mistake. delete does not set a pointer, which it deletes to NULL, so you have an infinite loop that may or may not be interrupted by the undefined behavior that you get from deleting the same pointer twice.

+3
source

This behavior is possible if the CSomeType instance knows the address where the pointer to itself is stored (CSomeType ** member in CSomeType) so that it can reset to delete it. I have no idea why this is necessary.

Example:

 struct self_know{ self_know** pptr; int cnt; static self_know* create(self_know **_pptr){ *_pptr = ::new self_know; (*_pptr)->cnt = 10; (*_pptr)->pptr = _pptr; return *_pptr; } void operator delete(void*it){ self_know *s = (self_know*)it; if(--s->cnt<0){ *(s->pptr)=0; ::delete s; } } }; #include<iostream> main(){ self_know *p = 0; self_know::create(&p); while( p != 0){ std::cout << p->cnt << std::endl; delete p; } } 
+2
source

Another possible theory is that someone played a nasty trick with a preprocessor. Say:

 struct delete_and_null { template<class T> delete_and_null& operator, (T*& p) { delete p; p = 0; return *this; } } delete_and_null; #define delete delete_and_null, 

This does not explain the need for a loop, but at least it avoids UB and ends in the end.

+2
source

It seems like an error if the CSomeType destructor CSomeType not in any way modify this object.

+1
source

not only is this probably a mistake, but it is an absolutely pointless check, since deleting a null pointer is fine. change to

 CCuriousClass::~CCuriousClass() { delete object; } 

or better yet, use a smart pointer and get rid of the destructor altogether.

+1
source

Check the definition of the CSomeType class. There may be an overload of the "! =" Function. Otherwise, this is clearly a mistake.

+1
source

The code seems to be wrong. Make sure that the destructor should not throw exceptions , otherwise it may exit the program, and it should be similar.

 CCuriousClass::~CCuriousClass() { try { if( object != NULL ) { delete object; object = NULL; } } catch(...) { } } 
0
source

I suspect this from a crazy C programmer who doesn't understand destructors and / or the delete operator. Either this, or someone who clumsyly hushed up "while" instead of "if" and did not know that delete already checks for null.

I will not waste time thinking about crazy code. It is important to know that this is stupid and crazy.

0
source

All Articles