Archived

This topic is now archived and is closed to further replies.

Oxyd

Chaning object's data before constructor and reading them after destructor

Recommended Posts

Oxyd    1157
I''m trying to write some garbage-collector (simillar to the one in enginuity). I''ve got some variables to hold object''s size, its reference count and iterator to the object in living (dead) objects list (std::list). In operator new, I first allocate the memory and then I reinterpret_cast it to Gc *. Add the object to list and set the var''s. In delete, I also reinterpret the pointer to Gc * and read the iterator, then I remove the object from the list using the iterator. It all works fine, till I try to use it with MI (I want one class to be garbage-collected, but I don''t want its parent to be so). The problem is in the operator delete. When I try to read the iterator to the object, it''s zeroed. I don''t know why, I don''t know how, but it happened. In no of the destructors I''m accessing it (because it''s private). But then I can''t remove the object from the objects list. Weird is that when I don''t have MI it doesn''t occur... Code is here:
typedef long addr;

#define GC Gc (sizeof (*this), (addr)this)

class Gc {
public:
	Gc (size_t size, addr self);
	Gc (const Gc &gc);
	virtual ~Gc () = 0;
	void *operator new (size_t size);
	void operator delete (void *mem);
	static void gc ();
	static void cleanup ();
	void addRef ();
	void removeRef ();
	static inline unsigned bytesAllocated ();
	static inline unsigned bytesGarbage ();
	static inline unsigned objectsAllocated ();
	static inline unsigned objectsGarbage ();
private:
	int ref;
	size_t objSize;
	bool stack;
	std::list <Gc *>::iterator self;
	bool gar; //is object garbage?

#ifdef DBG
	static unsigned allocations;
	static unsigned deallocations;
#endif		
	static unsigned allocated;
	static unsigned sizeGarbage;
	static unsigned numObjects;
	static unsigned numGarbage;
	static std::list <Gc *> objects;
	static std::list <Gc *> garbage;
};

unsigned Gc::bytesAllocated ()	{ return allocated; }
unsigned Gc::bytesGarbage ()	{ return sizeGarbage;}
unsigned Gc::objectsAllocated (){ return numObjects;}
unsigned Gc::objectsGarbage ()	{ return numGarbage;}

///--- CPP FILE ---///


Gc::Gc (size_t size, addr a)
  : ref (0),
    gar (true)
{
	Gc *o = reinterpret_cast <Gc *>(a);
	
	std::list <Gc *>::iterator me =	std::find (garbage.begin (), garbage.end (), o);

	objSize = size;

	if (me == garbage.end ())
		stack = true;
	else {
		stack = false;
		self = me;
	}
}

Gc::Gc (const Gc &gc)
{
	garbage.push_back (this);
	self = garbage.end ();	//nastavim pointr na sebe sama

	--self;
	ref = 0;				//je to vodpad

	gar = true;
	objSize = gc.objSize;
	stack = gc.stack;		
}

Gc::~Gc ()
{
}

void *Gc::operator new (size_t size)
{
	//nejdriv alokuju pamet

	void *mem = malloc (size);

	if (mem == 0)
		throw std::bad_alloc ();

	Gc *object = reinterpret_cast <Gc *>(mem);

	//zvysim pocitadlo alokovani

	++numGarbage;
	sizeGarbage+= size;

	//pridam objekt do seznamu objektu

	garbage.push_back (object);

#ifdef DBG
	++allocations;
#endif

	//vratim pamet

	return mem;
}

void Gc::operator delete (void *mem)
{
	if (mem == 0) return;
	
	Gc *object = reinterpret_cast <Gc *>(mem);
	
	//zjistim si velikost objektu

	int size = object->objSize;

	//smazu objekt ze seznamu

	if (object->gar) {
		garbage.erase (object->self);

		//snizim pocitadlo odpadku

		sizeGarbage-= size;
		--numGarbage;
	} else {
		objects.erase (object->self);

		//snizim pocitadlo objektu

		allocated-= size;
		--numObjects;
	}

#ifdef DBG
	++deallocations;
#endif

	//smazu objekt

	if (!object->stack)
		free (mem);
}

void Gc::addRef ()
{
	++ref;

	if (!stack && ref <= 1) {
		//objekt vstal z mrtvejch


		//odstranim ho ze seznamu odpadku

		garbage.erase (self);

		//pridam ho na seznam objektu

		objects.push_back (this);
		
		self = objects.end ();			//nastavim pointr na sebe sama

		--self;

		gar = false;

		//snizim pocitadlo odpadku

		--numGarbage;
		sizeGarbage-= objSize;

		//zvysim pocitadlo objektu

		++numObjects;
		allocated+= objSize;
	}
}

void Gc::removeRef ()
{
	--ref;

	if (!stack && ref <= 0) {
		//posledni reference k tomuhle vobjektu -> udelam z nej vodpad


		//smazu ho ze seznamu objektu

		objects.erase (self);

		//pridam ho k odpadkum

		garbage.push_back (this);
		
		self = garbage.end ();			//nastavim pointr na sebe sama

		--self;
		
		gar = true;

		//snizim pocitadlo objektu

		allocated-= objSize;
		--numObjects;

		//zvysim pocitadlo odpadku

		sizeGarbage+= objSize;
		++numGarbage;
	}
}

void Gc::gc ()
{
	//projedu celej seznam odpadku a vsechny je jeden po druhym vymazu

	std::list <Gc *>::iterator i = garbage.begin ();

	trace ("Gc::gc", garbage.size ());

	while (i != garbage.end ()) {
		std::list <Gc *>::iterator temp = i;
		++i;
		delete *temp;
	}

	//vymazu seznam odpadku

	garbage.clear ();
}

void Gc::cleanup ()
{
	//uvolnim neplatny objekty

	gc ();

	//uvolnim i ty platny objekty

	std::list <Gc *>::iterator it = objects.begin ();

	while (it != objects.end ()) {
		std::list <Gc *>::iterator temp = it;
		++it;

		delete *temp;
	}

	objects.clear ();
}

And this is how it''s derived:

template <typename T>
class DynMemArray : public Array <T>, public Gc {
public:
	DynMemArray () : Array <T> (), GC
	{ }

	DynMemArray (size_t size) : Array <T> (), GC
	{
		alloc (size);
	}

	DynMemArray (const DynMemArray <T> &r) : Array <T> (r), Gc (r)
	{ }

	~DynMemArray ()
	{
		//uvolnim pole

		if (mem) release (); //some internal stuff...

	}

        [etc...]
};

I''m sory for it''s so long and that there''re czech comments . Oxyd --- - Unreadable code is code written on a piece of paper, but not the one, in which the programmer is using a space in the place you don''t. - Real programmers aren''t afraid of goto

Share this post


Link to post
Share on other sites