Jump to content
  • Advertisement

Archived

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

sirSolarius

Deconstructor not firing...

This topic is 5371 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement
Thanks to everyone for sticking with this problem... it''s really been driving me crazy.

The header for MemoryManager:

/////////////////////////////////////////////////////////////////////////////

// MEMORYMANAGER.H

/////////////////////////////////////////////////////////////////////////////

//

// AUTHOR: ERIK GOLDMAN

// DATE: 6-5-04

// DESC: A singleton manager for memory objects- deletes objects with no references

// and allocates memory upon request.

// NOTES:

// TOFIX:

/////////////////////////////////////////////////////////////////////////////


#if !defined(AFX_MEMORYMANAGER_H__03E87D6A_9973_4814_A876_05F7B8C4AA5C__INCLUDED_)
#define AFX_MEMORYMANAGER_H__03E87D6A_9973_4814_A876_05F7B8C4AA5C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


class MemObj;

#include <list>

class MemoryManager
{
protected:
MemoryManager();
~MemoryManager();
std::list<MemObj*> m_deadObjects;
std::list<MemObj*>::iterator m_iter, m_tempIter;
static MemoryManager *instance;

public:
static MemoryManager *getInstance();
void checkMemory();

void markForDeletion(MemObj *m);

void Destroy();
};

#endif // !defined(AFX_MEMORYMANAGER_H__03E87D6A_9973_4814_A876_05F7B8C4AA5C__INCLUDED_)



And no, I don''t think I''m deleting a void pointer, but how could I tell? Are you sure that forward declaring MemObj isn''t affecting anything?

Share this post


Link to post
Share on other sites
Here''s my suggestion:

0) First, I think your problem is this:

MemPtr escape=new Functor(&ExitProgram);

The above creates an object that has a reference count of TWO, not ONE. Correct?

2) You could post your function for Functor (you never did that but I assume it derives from MemObj)

3) Delete your elements in this way:


iter = m_deadObjects.begin();
while(iter != m_deadObjects.end()) {
delete *iter;
*iter = NULL;
++iter;
}
m_deadObjects.clear();


The above ensures that no iterators are invalidated and that you loop through all objects.

Regards,
Jeff


[ CodeDread ]

Share this post


Link to post
Share on other sites
quote:
Original post by rypyr
Here''s my suggestion:

0) First, I think your problem is this:

MemPtr escape=new Functor(&ExitProgram);

The above creates an object that has a reference count of TWO, not ONE. Correct?

2) You could post your function for Functor (you never did that but I assume it derives from MemObj)

3) Delete your elements in this way:


iter = m_deadObjects.begin();
while(iter != m_deadObjects.end()) {
delete *iter;
*iter = NULL;
++iter;
}
m_deadObjects.clear();


The above ensures that no iterators are invalidated and that you loop through all objects.

Regards,
Jeff


[ CodeDread ]



1) Why does that have a ref count of 2? I''m pretty sure that''s my problem, too, but why does that happen? MemPtr escape= new Functor()... that just has one MemPtr pointing to it, right?

2)

#ifndef _ERIK_FUNCTOR_H_DEFINED
#define _ERIK_FUNCTOR_H_DEFINED

/////////////////////////////////////////////////////////////////////////////

// FUNCTOR.H

/////////////////////////////////////////////////////////////////////////////

//

// AUTHOR: ERIK GOLDMAN

// DATE: 6-3-04

// DESC: Encapsulated function pointers- standard and for member pointers

// NOTES: I haven''t tried these yet

// TOFIX:

/////////////////////////////////////////////////////////////////////////////


#include "MemObj.h"

class Functor:public MemObj
{
protected:
void (*fp)(); // void function pointer

public:
virtual void operator()()
{
(*fp)();
}

Functor(void (*f)())
:fp(f)
{
}

Functor(const Functor &f)
:fp(f.fp)
{
}
};

/////////////////////////////////////////////////////////////////////////////

// CLASSFUNCTOR

/////////////////////////////////////////////////////////////////////////////

//

// AUTHOR: ERIK GOLDMAN

// DATE: 6-3-04

// DESC: A functor that allows usage of a member variable

// NOTES:

// TOFIX:

/////////////////////////////////////////////////////////////////////////////


template<class tClass> class ClassFunctor:public Functor
{
private:
void (tClass::*fPtr)(); // pointer to member function

tClass* objPtr; // pointer to object


public:

// constructor - takes pointer to an object and pointer to a member and stores

// them in two private variables

ClassFunctor(tClass* _pt2Object, void(tClass::*_fpt)())
:objPtr(_pt2Object), fPtr(_fpt)
{
}

ClassFunctor(const ClassFunctor &c)
:objPtr(c.objPtr), fPtr(c.fPtr)
{
}

// override operator "()"

virtual void operator()()
{
(*objPtr.*fPtr)();
}

virtual void set(tClass *c, void(tClass::*fp)())
{
objPtr=c;
fPtr=fp;
}
};

/////////////////////////////////////////////////////////////////////////////

// MEMCLASSFUNCTOR

/////////////////////////////////////////////////////////////////////////////

//

// AUTHOR: ERIK GOLDMAN

// DATE: 6-3-04

// DESC: A memory-managed version of the ClassFunctor- this counts as a

// reference to a MemObj

// NOTES:

// TOFIX:

/////////////////////////////////////////////////////////////////////////////


template<class t> class MemClassFunctor:public ClassFunctor<t>
{
private:
void (t::*fPtr)(); // pointer to member function

MemPtr<t> objPtr; // pointer to object


public:

// constructor - takes pointer to an object and pointer to a member and stores

// them in two private variables

MemClassFunctor(t* _pt2Object, void(t::*_fpt)())
:objPtr(_pt2Object), fPtr(_fpt)
{
}

MemClassFunctor(const MemClassFunctor &m)
:objPtr(m.objPtr), fPtr(m.fPtr)
{
}

// override operator "()"

virtual void operator()()
{
(*objPtr.*fPtr)();
}

void set(t *c, void(t::*fp)())
{
objPtr=c;
fPtr=fp;
}
};
#endif


3) Ok, I changed to your code, but no improvement.

Share this post


Link to post
Share on other sites
Step through with your debugger and you''ll see. I would think you would have already done that.

My guess: The compiler is first executing MemPtr(T*) to convert your pointer into a MemPtr object (ref 1), then it''s calling operator= (ref 2). If you want to avoid the implicit conversion you should use the "explicit" keyword on the constructor. Or you could do:

MemPtr escape(new Functor(&ExitProgram));


[ CodeDread ]

Share this post


Link to post
Share on other sites
Thinking about it some more, your whole problem stems from allowing easy conversion/casting from the pointer type to the smart pointer object. This is never a good thing because you give the compiler too much flexibility and you can easily lose track of temporary objects. I think the best bet is to make your constructor explicit so that implicit casts are not being done willy-nilly.

Regards,
Jeff


[ CodeDread ]

Share this post


Link to post
Share on other sites
But even if temporary references are created, the reference counter is still decremented when the temporary MemPtr''s are destructed. I stepped through the code and there are, in fact, two references to the object- but one is from escape, and the other is from within the keymap itself.

The fundamental problem here is that the keymap''s destructor isn''t firing. Even if I should be avoiding implicit casts, etc., that''s the core issue. There has to be some reason that keymap''s destructor fails to get called, ever, and I can''t figure out what it is.

Share this post


Link to post
Share on other sites
Ok, I still think that''s your problem somehow though. Did you try changing it to:

MemPtr<inputKeymap> keymap(new InputKeymap());
MemPtr escape(new Functor(&ExitProgram));

?

Regards,
Jeff


[ CodeDread ]

Share this post


Link to post
Share on other sites
Hello sirSolarius,

I think I might have found the problem if not it could still be a problem.

In InputKeymap::Erase() your are iterating over the map and calling Unassign which is erasing a key form the map.
Since a map is hash based or tree base the minute you erase the key you have now change how the iterator will traverse the map.
This is very bad and I have seen this happen with maps before
iterating and then erasing the contiuning on.
The maps erase should return an iterator of the next element.
I say should because on Sun compiler erase retuns void.

What you might have to do is save a tmp iterator and increament this to point to the next, then call Unassign then asign back the tmp iterator back to your iter.


std::map<int, MemPtr<Functor> >::iterator tmp;
while(iter != m_keymap.end()) // end could change as you erase iterators

{
tmp=iter;
++tmp;
Unassign(iter->first); // set the functor to 0 for memory management

iter=tmp;
}


Lord Bart




[edited by - lord bart on June 9, 2004 9:14:57 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I haven''t looked through your code but I''ve come across the same problem where delete is definitely called but the destructor isn''t.

The problem was that I was deleting an incomplete type (i.e. a type that has only been forward declared at the site of the delete.) The solution is simply to include the header file for the type being deleted in the source file where delete is called.

Hope this helps.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!