/*
*  Descripcion:
*		Las funciones definidas en este fichero reemplazan a new y delete
*	de C++. Llevan una contabilidad de punteros a los que se asigna memoria
*	y de los que se libera memoria, provocando un core en caso de liberar
*	memoria que ya ha sido previamente liberada o que nunca se ha asignado.
*
*		Su unica funcion es para depuracion.
*
*	Basta compilar el programa principal que se quiere depurar lincando
*	con la libreria -lnew generada por este fichero. No es necesario
*	tocar fuentes ni recompilar librerias ya compiladas. -lnew debe ser
*	la ultima libreria en la lista de librerias al compilar. Por ejemplo
*
*	CC programa.cc -llibreria1 -llibreria2 ... -lnew
*
*
*/

#include <stdlib.h>
#include <iostream.h>

int Contador_Memoria = 0;

//
// Array maximo de punteros contabilzados.
//
#define MAXIMO_PUNTEROS 200000
int tabla[MAXIMO_PUNTEROS];
int tamanos[MAXIMO_PUNTEROS];

//
// Operador new. La primera vez que se le llama inicializa el array de
// punteros con todo a cero.
//	Cada vez que se le llama, crea la memoria pedida y devuelve el 
//	puntero correspondiente. Guarda dicho puntero en el array en la
//	primera posicion vacia que encuentre.
//
void *operator new(size_t tamano)
{
	static int Primera_Vez = 1;
	int i;

	void *p;

	if (Primera_Vez == 1)
	{
		for (i=0; i<MAXIMO_PUNTEROS; i++)
			tabla[i] = 0;
		Primera_Vez = 0;
	}

	p = malloc (tamano);
	Contador_Memoria = Contador_Memoria + tamano;

	for (i = 0; i< MAXIMO_PUNTEROS;i++)
	{
		if (tabla[i] == 0)
		{
			tabla[i] = (int)p;
			tamanos[i] = tamano;
			break;
		}
	}

	if (i==MAXIMO_PUNTEROS)
		cout << "--- Sobrepasado limite punteros ---" << endl;

	return p;
}

//
// Operador delete. Busca en el array de punteros el que se le ha pasado.
// Si lo encuentra, lo libera y lo borra del array. Si no lo encuentra,
//	genera un core. mostrando un mensaje de aviso
//
void operator delete (void *cp)
{
	for (int i = 0; i < MAXIMO_PUNTEROS; i++)
	{
		if ((int)cp == tabla[i])
		{
			free (cp);
			tabla[i] = 0;
			Contador_Memoria = Contador_Memoria - tamanos[i];
			tamanos[i] = 0;
			return;
		}
	}
	
	cout << "--- Liberado puntero erroneo ---" << endl;

	// genera core
	int *a=NULL;
	*a=0;
}

//
// Operadore delete[]. Algunos compiladores necesitan que new[] y delete[]
//	sean definidos como funciones distintas. En el compilador CC de solaris
//	no es necesario. new[] llama a new y delete[] llama a delete
/***
void operator delete [](void *cp)
{
	for (int i = 0; i < MAXIMO_PUNTEROS; i++)
	{
		if ((int)cp == tabla[i])
		{
			free (cp);
			tabla[i] = 0;
			return;
		}
	}
	
	cout << "--- Liberado puntero[] erroneo ---" << endl;

	// genera core
	int *a=NULL;
	*a=0;
}
***/

