public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* check that a member function really operates on an object of the  expected type
@ 2009-04-14  9:18 Erik
  2009-04-14 14:36 ` Ian Lance Taylor
  0 siblings, 1 reply; 5+ messages in thread
From: Erik @ 2009-04-14  9:18 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 960 bytes --]

A common kind of bug is that a member function (method) operates on an
object that is not (any more) of the expected type. This can happen in
badly designed code, with redundant parent references (that become
stale) and destructors that are misused to do something else than
releasing resources. To catch these errors, one would have to add an
assertion in the form of a dynamic_cast to the beginning of every method:
void Some_Type::some_method() {
    dynamic_cast<Some_Type
&>(static_cast<Root_Ancestor_Type_Of_Some_Type &>(*this));
    //  do something
}

This will throw std::bad_cast if the bug in question is encountered. Of
course it is not practically possible to add such an assertion to the
beginning of every method, but there should be a compiler flag to enable
this (in debug builds). Is there such a flag? Is there a feature request
for it? If not, I will add one. I attach a little example of this bug in
a real but trimmed down piece of code.

[-- Attachment #2: prov.cc --]
[-- Type: text/x-c++src, Size: 1430 bytes --]

#include <cassert>

namespace UI { //  the widget set (UI toolkit)

struct Panel {
	Panel (Panel * const Parent) :
		_parent(Parent), _firstchild(0), _lastchild(0)
	{
		assert(Parent != this);
		if (_parent) {
			_next = _parent->_firstchild;
			_prev = 0;
			if (_next)
				_next->_prev = this;
			else
				_parent->_lastchild = this;
			_parent->_firstchild = this;
		} else
			_prev = _next = 0;
	}

	virtual ~Panel() {
		while (_firstchild)
			delete _firstchild;
		if (_parent) {
			if (_prev)
				_prev->_next = _next;
			else
				_parent->_firstchild = _next;
			if (_next)
				_next->_prev = _prev;
			else
				_parent->_lastchild = _prev;
		}
	}

	Panel * parent() const {return _parent;}

private:
	Panel * _parent;
	Panel *_next, * _prev;
	Panel *_firstchild, *_lastchild;
};

}


//  the main user interface of the application
struct Main_User_Interface : public UI::Panel {
	Main_User_Interface () : UI::Panel (0) {}
	void set_need_redraw() {
		dynamic_cast<Main_User_Interface &>(static_cast<UI::Panel &>(*this));
	}
};

//  a little window that can be open in the main user interface
struct Some_Window : public UI::Panel {
	Some_Window (Main_User_Interface & Parent) :
		UI::Panel (&Parent), m_parent(Parent)
	{}
	~Some_Window () {m_parent.set_need_redraw();}
private:
	Main_User_Interface & m_parent;
};

int main() {
	Main_User_Interface main_user_interface;
	new Some_Window (main_user_interface);
	return 0;
}

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-04-14 17:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-14  9:18 check that a member function really operates on an object of the expected type Erik
2009-04-14 14:36 ` Ian Lance Taylor
2009-04-14 16:35   ` Erik
2009-04-14 16:54     ` Ian Lance Taylor
2009-04-14 17:05       ` Erik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).