revisión Nº 14 del código (espero sea la final, por lo menos dejó de tirar excepciones.. xD) junto con explicación ... a alguien le puede servir algún día... (a mi me habría servido...)
#include <windows.h>
using namespace std;
#include <new>
#include <memory>
#ifndef xgCOLLECTTIME
#define xgCOLLECTTIME 30000
#endif
class xgGCNodo{
friend class xgGC;
private:
xgGCNodo(void *value){
val = value;
next = NULL;
bDel = false;
}
xgGCNodo * next;
bool bDel;
void * val;
};
/*******************************************************************/
//
/*******************************************************************/
class xgObject{
protected:
xgObject(){};
public:
virtual ~xgObject(){}
/* static */ void* operator new(size_t sz)throw (bad_alloc);//always is static...
/* static */ void operator delete(void* m)throw();//always is static...
/* static */ void* operator new[](size_t sz)throw (bad_alloc);//always is static...
/* static */ void operator delete[](void* m)throw();//always is static...
};
/*******************************************************************/
//
/*******************************************************************/
class xgGC{
private:
xgGC();
~xgGC();
//Pure Memory and List operations...
void *Append(size_t sz)throw (bad_alloc);
void Remove(void *val)throw();
public:
//Memory operations...
static xgGC *StartCollect()throw();
static void *Alloc(size_t sz)throw (bad_alloc);
static void Free(void *val)throw();
static int ForceCollect()throw();
static void FreeCollect()throw();
HANDLE xgGetExitEvent(){return hExitEvent;}
private:
//Collect timing Thread
static DWORD WINAPI xgCollectThread(LPVOID params);
//Extern operations
static xgGC *GetpGC();
int Collect()throw();
void FreeObjects()throw();
xgGCNodo *first,*last;
unsigned int nelem;
DWORD cThid;HANDLE hExitEvent;
static class xgGC* pgc;
};
/*******************************************************************/
//
/*******************************************************************/
class xgGC* xgGC::pgc=NULL;
xgGC::xgGC(){
pgc=NULL;nelem=0;
first=last=NULL;
//Creamos Evento...
hExitEvent=CreateEvent(NULL,FALSE,FALSE,"#XGGC#EXITEVENT#XGGC#");
if(hExitEvent)
CreateThread(NULL,0,xgCollectThread,(void *)this, 0, &cThid);
}
xgGC::~xgGC(){
if(hExitEvent){
SetEvent(hExitEvent);
CloseHandle(hExitEvent);
hExitEvent=NULL;
}
FreeObjects();
}
xgGC* xgGC::GetpGC(){
return pgc;
}
xgGC *xgGC::StartCollect()throw(){
if(!pgc)pgc=new xgGC;
return pgc;
}
void* xgGC::Alloc(size_t sz)throw (bad_alloc){
if(pgc)return pgc->Append(sz);
else return operator new(sz);
}
void xgGC::Free(void *val)throw(){
if(pgc)pgc->Remove(val);
else operator delete(val);
}
int xgGC::ForceCollect()throw(){
if(pgc)pgc->Collect();
}
void xgGC::FreeCollect()throw(){
if(pgc)delete pgc;
}
//Append new item...
void *xgGC::Append(size_t sz)throw (bad_alloc){
void *m=operator new(sz);
if(m){
xgGCNodo *pt=new xgGCNodo(m);
if(first==NULL)first = pt;
else last->next = pt;
last=pt;++nelem;
}
return m;
}
//Mark for delete...
void xgGC::Remove(void *val)throw(){
for(xgGCNodo *pt=first;pt&&val;pt=pt->next)
if(pt&&pt->val==val){
pt->bDel=true;
break;
}
}
//Free marked memory...
int xgGC::Collect()throw(){
xgGCNodo *pt=first;
xgGCNodo *nxt,*prv= NULL;
while(pt){
nxt = pt->next;
if(pt->bDel==true){
//Reorganice list..
if(first==pt)first=nxt;
else prv->next=nxt;
//Free memory...
operator delete(pt->val);
delete pt;--nelem;
}else
prv = pt;
pt = nxt;
}
return nelem;
}
/*******************************************************************/
//
/*******************************************************************/
void* xgObject::operator new(size_t sz)throw (bad_alloc){
return xgGC::Alloc(sz);
}
void xgObject::operator delete(void* m)throw(){
xgGC::Free(m);
}
void* xgObject::operator new[](size_t sz)throw (bad_alloc){
return operator new(sz);
}
void xgObject::operator delete[](void* m)throw(){
operator delete(m);
}
/*******************************************************************/
//
/*******************************************************************/
void xgGC::FreeObjects()throw(){
xgGCNodo *nxt=NULL,*pt=first;
while(pt){
nxt=pt->next;
if(pt->val){
if(!pt->bDel)//Call destructor...
delete (xgObject *)pt->val;
//Free memory...
operator delete(pt->val);
}
delete pt;pt=nxt;
}
first=NULL;
pgc=NULL;
}
/*******************************************************************/
//
/*******************************************************************/
DWORD WINAPI xgGC::xgCollectThread(LPVOID params){
xgGC *pGC=(xgGC*)params;
if(pGC){
HANDLE hExitEvent=pGC->xgGetExitEvent();
for(;;){
DWORD dwRes=WaitForSingleObject(hExitEvent,xgCOLLECTTIME);
switch(dwRes){
case WAIT_TIMEOUT:
pGC->Collect();
break;
case WAIT_ABANDONED_0:case WAIT_OBJECT_0:
ExitThread(0);
break;
}
}
}
//Finalizamos thread...
ExitThread(0);
}
/*******************************************************************/
//
/*******************************************************************/
class foo:public xgObject{
public:
foo(){n=100;printf("foo created\n",n);}
~foo(){printf("foo deleted\n",n);}
void asdf(){printf("%d\n",n);}
private:
int n;
};
int main(void){
xgGC::StartCollect();
int av,*p;
printf("\n\n");
foo *b=new foo;
b->asdf();
//delete b;
xgGC::FreeCollect();
system("pause");
return 0;
}
definición:
http://es.wikipedia.org/wiki/Recolecci%C3%B3n_de_basuraconceptos generales: un recolector de basura se basa en la sobrecarga de los operadores new y delete (o definiendo funciones Xmalloc Xfree en C), existen de dos tipos, los que administran la memoria directamente (como un único bloque) se encargan de ir redimencionando dicho bloque para poder responder a las solicitudes de memoria, o (como yo lo implementé) mediante listas que no exige el uso de templates (los espacios de memoria se reservan directamente, pero no se utilizan directamente), utilicé este método porque... cuanto más controles se le pone al uso de los punteros... más recursos se utilizan... (y no quiero un visual basic)...

sobre la sobre carga de new y delete... hay poca información... (sobre todo en español) o está incompleta... pero... básicamente hay dos formas de sobreescribir new y delete, una global y la otra por clase:
redefinición global:
operator new(size_t sz)throw (bad_alloc){
}
operator delete(void* m)throw(){
}
el problema de la redefinición global es que no nos permite personalizar demasiado el comportamiento (como es global reemplaza las standares de C++) y nos deja a la merced de muchos errores en tiempo de ejecución (los standares ya previeron la mayoría de ellos)... por lo tanto lo mejor es la redefinición local (en clases).
class xgObject{
protected:
xgObject(){};
public:
virtual ~xgObject(){}
/* static */ void* operator new(size_t sz)throw (bad_alloc);//always is static...
/* static */ void operator delete(void* m)throw();//always is static...
/* static */ void* operator new[](size_t sz)throw (bad_alloc);//always is static...
/* static */ void operator delete[](void* m)throw();//always is static...
};este tipo de clases están definidas en todos los frameworks y/o lenguajes (smalltalk, java, mfc, xgWidgets, y muchos otros), lo que hace es definir una clase "general" que permite definir un nuevo comportamiento de los operadores new y delete (entre otras cosas) de todas las clases que la hereden (no de tipos puros)... (un detalle poco documentado de C++ es que la sobrecarga de los operadores (new y delete) siempre serán estáticos... por más que no se lo defina).
la clase xgGC() es una clase especial, está definida para que no pueda ser creada más de una vez... (de todas formas se la puede corromper intencionalmente)... esta clase lo único que hace es ir almacenando una referencia (puntero) a cada espacio de memoria reservado, y al eliminarlo marcarlo (no lo elimina directamente) para ser eliminado, esta clase a su vez, crea un thread (hilo de ejecución) encargado de ir eliminado los espacios de memoria marcados para eliminar, (con este detalle se corrigen un par de errores complicados de corregir en proyectos grandes, por eso la cree), además de eso, (en su destructor) incluye una rutina que liberará los espacios de memoria reservados no liberados con lo cual eliminará los "memory leaks"... esperando que alguien le sirva lo explicado... me despido...

S2