Archived

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

vbisme

Pointer releasing memory for itself?

Recommended Posts

How can a pointer be used to release memory within itself? For example, take the DirectDraw object. You could call DDObj->Release() and everything is taken care of.

Share this post


Link to post
Share on other sites
Hi,

DirectX is built using the Component Object Model (COM). When you call Release() for an object the object iteself is not actually freeing any resources.

Instead, the Release() function tells COM to free any memory that it previously allocated for the object. COM basically sits between your application and the DirectX objects.


Regards,

Michael

Share this post


Link to post
Share on other sites
there is nothing unique to COM that makes this functionality available--it is basically just a smart pointer. It is a class that keeps the pointer internally, and then keeps a reference count on how many people are using that pointer (when you call AddRef it increments this count), and then when you call Release, it decrements that count and when the count reaches zero, it calls free on the pointer.

--michael

Share this post


Link to post
Share on other sites
quote:
Original post by vbisme
How can a pointer be used to release memory within itself?

Because it points to an object that contains a method (or methods) to do so.

quote:
For example, take the DirectDraw object. You could call DDObj->Release() and everything is taken care of.

The comments above have responded to DirectX/COM issues. I''ll respond to generic object pointer (or pointer to object) issues:

class CSomeClass
{
public:
CSomeClass(...);
bool Alloc(...);
bool Release(...);
private:
// data
};
//
// in some function somewhere:
CSomeClass *pSCObj; // pSCObj is a pointer. Currently it points to nothing.
pSCObj = new CSomeClass(...); // pSCObj now points to an instance of class CSomeClass
pSCObj->Alloc(...); // method of class CSomeClass called through pointer (interface)
// use pSCObj
pSCObj->Release(...);




I wanna work for Microsoft!

Share this post


Link to post
Share on other sites
Actually,

delete pSCObj;

is needed. This is the issue that I was trying to point out. How could pSCObj call a class that would ultimately execute "delete" upon itself?

Share this post


Link to post
Share on other sites
quote:
Original post by rileyriley
void SomeClass::Release() {
delete this;
}

bam!


See also

void f() {
SomeClass a();
...
}

Kerpow!!

If you simply must delete this , make all constructors private (or protected) and have a static method that returns a pointer to SomeClass allocated with new. The easy way do this sort of thing is with the boost library's shared_ptr and shared_arr. The general rule is to never call new for someone else, nor to call delete for something you did not allocate. this rule gets broken a lot but delete this is almost begging for serious trouble.


Edited by - grib on November 7, 2001 6:32:46 PM

Edited by - grib on November 7, 2001 6:34:54 PM

Share this post


Link to post
Share on other sites
Typical implementation of AddRef and Release

    
class CMyCoClass
{
public:
CMyCoClass() : m_cRef(1)
{}

ULONG AddRef
{
InterlockedIncrement(m_cRef);
return m_cRef;
}

ULONG Release
{
InterlockedDecrement(m_cRef);
ULONG cRef = m_cRef;
if(0==m_cRef)
delete this;
return cRef;
}

private:
long m_cRef;
};


Magmai Kai Holmlor
- Not For Rent

Edited by - Magmai Kai Holmlor on November 8, 2001 3:03:54 AM

Share this post


Link to post
Share on other sites
quote:
From: vbisme, How can a pointer be used to release memory within itself? For example, take the DirectDraw object. You could call DDObj->Release() and everything is taken care of.
As an example lets say we have this code;

LPDIRECTDRAW lpDD;
DirectDrawCreate(0 , &lpDD, 0);
lpDD->Release();

1. lpDD is a pointer to a DirectDraw object
2. The first variable of DirectDraw is a pointer to a class of functions
3. Release is one of those functions, ie: lpDD->Functions->Release();
4. Release can be thought of as a static member of a DirectDrawFunction class
5. It is hidden from you but Release actual passes lpDD as a parameter, ie: lpDD->Functions->Release(lpDD);
6. Calling Release doesn't do anything to lpDD
7. Calling Release doesn't do anything to the class of functions
8. Release only deletes the memory associated with that DirectDraw object

The code below shows an example of how this could be done.


  
class DirectDrawFunctions;
//

class DirectDrawObject
{
public:
DirectDrawFunctions *Functions;
//whatever else it has is hidden from us

};
//

class DirectDrawFunctions
{
public:
static Release(DirectDrawObject *pDDO) { delete pDDO; }
//static SetCooperativeLevel();

//static SetDisplayMode();

//etc

};
//

DirectDrawFunctions DDF;
//

void DirectDrawCreate(DirectDrawObject **ppDDO)
{
*ppDDO = new DirectDrawObject;
(*ppDDO)->Functions = &DDF;
}
//

void main(void)
{
DirectDrawObject *lpDDO;
DirectDrawCreate(&lpDDO);
lpDDO->Functions->Release(lpDDO);
}



Edited by - burp on November 8, 2001 5:35:34 AM

Share this post


Link to post
Share on other sites
quote:
Original post by vbisme
delete pSCObj; is needed. This is the issue that I was trying to point out. How could pSCObj call a class that would ultimately execute "delete" upon itself?



It sounds like you want to have a class ''Foo'' which has allocated some memory, and you want the memory to be freed when you do a ''delete pSCObject''?

If yes, you need a destructor:

  
// Called when deletion occurs - *before* the class is

// actually destroyed. Now you can get rid of any memory

// that the class allocated.

CSomeClass::~CSomeClass ()
{
Release();
}


Now, there is no way, in C++, to make a class that will destroy itself when there are no more pointers to it (i.e., it has no references). You can make a ''fake'' pointer class and set it up so that it keeps count of the references to its target, those classes are known as smart pointers , for obvious reasons.

  
class CSomeClass {
...
}
class PSomeClass {
CSomeClass *pSC;
int *refCount;
...
}


You need to overload the constructors and destructor, and the * and = operators of PSomeClass to make sure that the reference count is kept correctly.

However, this method of reference counting isn''t perfect. It''ll keep an object alive if it has any references, even if those references are not accessible. For example, a node in a tree class might reference its parent and its children. The parent node would reference its children, including the original node. Although the tree might be inaccessible to the rest of the program, it still has references.

True garbage collection keeps a track of which objects are currently visible. Because C++ is not designed for gc it is extremely difficult to make a class heirarchy that uses it. It is best, therefore, to manually free memory when you can, and possibly use reference counting when you know that a reference cannot be recursive - I have a reference counting String class because I know that the string can''t contain a reference to itself.

All your bases belong to us

Share this post


Link to post
Share on other sites