]> git.llucax.com Git - z.facultad/75.42/calculadora.git/commitdiff
Se termina el malloc debugger, incluyendo un test simple (falta documentar).
authorLeandro Lucarella <llucax@gmail.com>
Sun, 14 Sep 2003 04:23:49 +0000 (04:23 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Sun, 14 Sep 2003 04:23:49 +0000 (04:23 +0000)
Makefile
dllist.h
documentacion.h
memdebug.c [new file with mode: 0644]
memdebug.h [new file with mode: 0644]
memdebug_debugger.h [new file with mode: 0644]
memdebug_test.c [new file with mode: 0644]
meminfo.c [new file with mode: 0644]
meminfo.h

index f5a610a6b22ef7f79dd8e699fc3b7bdee3b28404..afa2713649f0c88e50d73923ced0f25803c3a7f5 100644 (file)
--- a/Makefile
+++ b/Makefile
 #
 
 # Opciones para el compilador.
-CFLAGS=-ansi -pedantic -Wall -g3
+CFLAGS=-ansi -pedantic -Wall -g3 -DDEBUG
+CC=gcc-3.2
 
+# Pruebas.
+TESTS=dllist_test memdebug_test
 # Programa a compilar.
-TARGETS=
+TARGETS=$(TESTS)
 
 # Regla por defecto.
 all: tp1
 
 # Pruebas.
-tests: dllist_test
+tests: $(TESTS)
        ./dllist_test
+       ./memdebug_test
 
 dllist_test: dllist.o
 
+memdebug_test: dllist.o meminfo.o memdebug.o
+
 tp1: $(TARGETS)
 
 # Regla para borrar.
index ad88060df3402a93e3d6ea386b678b7aa001e8cf..10edb6c9a6f693a47f2277debcbb3f39935a8370 100644 (file)
--- a/dllist.h
+++ b/dllist.h
@@ -17,7 +17,6 @@
 #ifndef DLLIST_H
 #define DLLIST_H
 
-
 /** Tipo de dato booleano. */
 typedef enum {
     FALSE,      /**< Falso. */
index 353654a2a743adc78e9e235dea14bf74d682d89c..190ad2a8e30c925a4ea6d3b360d05966c62b45ce 100644 (file)
@@ -150,4 +150,10 @@ b = b * 2
 
             Puede suponerse que estas ecuaciones son válidas.
 
+\section conclusiones Conclusiones.
+
+Problemas:
+    - "Sobrecarga" de malloc. Lo hacía antes de un #include <stdlib.h> y me
+      tiraba un error porque la definicion de la stdlib me expandía el macro.
+    - 
 */
diff --git a/memdebug.c b/memdebug.c
new file mode 100644 (file)
index 0000000..bb91640
--- /dev/null
@@ -0,0 +1,136 @@
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: sáb ago 30 20:08:45 ART 2003
+ *
+ * $Id$
+ */
+
+#include "memdebug.h"
+#include "dllist.h"
+#include "meminfo.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * Lista interna a utilizar en memdebug_malloc() y memdebug_free().
+ */
+static DLList* memdebug_list;
+
+/**
+ * FIXME la búsqueda se realiza de atrás hacia adelante para que sea más
+ * eficiente, ya que generalmente se borra primero la memoria que se pidió
+ * úitima.
+ */
+bool memdebug_DLList_find(DLList* list, void* ptr) {
+    MemInfo* i;
+    for (i = DLList_end(list); DLList_have_more(list); i = DLList_prev(list)) {
+        if (i->pointer == ptr) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+void memdebug_info_print(MemInfo* mi, FILE* fp) {
+    char fecha[30];
+    struct tm* ltime;
+    ltime = localtime(&(mi->time));
+    strftime(fecha, 30, "%c", ltime);
+    fprintf(fp, "0x%08X | %5u | %-25s | %-16s | %5u\n",
+            (size_t)(mi->pointer),
+            mi->bytes,
+            fecha,
+            mi->filename,
+            mi->fileline);
+}
+
+void memdebug_list_print(FILE* fp) {
+    MemInfo* mi;
+    fprintf(fp, "%-10s | %-5s | %-25s | %-16s | %-5s\n",
+            "Ptr",
+            "Bytes",
+            "Fecha",
+            "Archivo",
+            "Línea");
+    fprintf(fp, "-----------+-------+---------------------------+"
+            "------------------+------\n");
+    for (mi = DLList_begin(memdebug_list);
+            DLList_have_more(memdebug_list);
+            mi = DLList_next(memdebug_list)) {
+        memdebug_info_print(mi, fp);
+    }
+}
+
+void* memdebug_malloc(size_t bytes, const char* fname, size_t fline) {
+    void* ptr;
+    /* Si no está creada la lista global, la creo (o intento). */
+    if (!memdebug_list) {
+        memdebug_list = DLList_new();
+        /* Si no se puede crear la lista no reservo memoria, devuelvo NULL. */
+        if (!memdebug_list) {
+#ifdef DEBUG
+            fprintf(stderr, "%s: No se pudo crear la lista interna "
+                            "(llamado desde %s, línea %i).\n",
+                    __FILE__, fname, fline);
+#endif
+            return NULL;
+        }
+    }
+    /* Intento reservar memoria pedida. */
+    ptr = malloc(bytes);
+    /* Si se puedo reservar, creo un nuevo nodo y lo agrego a la lista. */
+    if (ptr) {
+        MemInfo* mi = MemInfo_new(ptr, bytes, fname, fline);
+        /* Si no se puede crear el nodo, devuelvo NULL. */
+        if (!mi || !DLList_push(memdebug_list, mi)) {
+#ifdef DEBUG
+            fprintf(stderr, "%s: No se pudo crear el nodo para 0x%X "
+                            "(llamado desde %s, línea %u).\n",
+                    __FILE__, (size_t)ptr, fname, fline);
+#endif
+            return NULL;
+        }
+    }
+    return ptr;
+}
+
+void memdebug_free(void* ptr) {
+    /* Busca en la lista y de encontrarlo nos lo deja en el elemento actual. */
+    if (memdebug_DLList_find(memdebug_list, ptr)) {
+        /* Lo encontró, elimino el nodo actual. */
+        DLList_remove_current(memdebug_list);
+#ifdef DEBUG
+    } else {
+        fprintf(stderr, "%s: No se encontro el ptr 0x%X en la lista.\n",
+                __FILE__, (size_t)ptr);
+#endif
+    }
+    /* Lo encuentre o no, trata de liberar la memoria. */
+    free(ptr);
+}
+
+void memdebug_end(void) {
+    /* Si hay una lista. */
+    if (memdebug_list) {
+        MemInfo* mi;
+        /* Imprimo la lista. */
+        memdebug_list_print(stderr);
+        /* Libero la memoria de cada elemento y cada puntero almacenado. */
+        while (!DLList_empty(memdebug_list)) {
+            mi = DLList_pop(memdebug_list);
+            free(mi->pointer);
+            MemInfo_delete(mi);
+        }
+    }
+}
+
diff --git a/memdebug.h b/memdebug.h
new file mode 100644 (file)
index 0000000..33bf638
--- /dev/null
@@ -0,0 +1,49 @@
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: sáb ago 30 20:08:45 ART 2003
+ *
+ * $Id$
+ */
+
+#ifndef MEMDEBUG_H
+#define MEMDEBUG_H
+
+#include "dllist.h"
+#include "meminfo.h"
+/* Para usar FILE. */
+#include <stdio.h>
+
+/**
+ * @todo FIXME
+ */
+void* memdebug_malloc(size_t bytes, const char* fname, size_t fline);
+
+/**
+ * @todo FIXME
+ */
+void memdebug_free(void* ptr);
+
+/**
+ * Imprime una DLList en un archivo.
+ *
+ * \param list DLList a imprimir.
+ * \param fh   Puntero al archivo a escribir.
+ */
+void memdebug_list_print(FILE* fp);
+
+/**
+ * @todo FIXME
+ * Imprime la lista de memoria no liberada, la libera y borra la lista interna.
+ */
+void memdebug_end(void);
+
+#endif /* MEMDEBUG_H */
diff --git a/memdebug_debugger.h b/memdebug_debugger.h
new file mode 100644 (file)
index 0000000..3150261
--- /dev/null
@@ -0,0 +1,48 @@
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: sáb ago 30 20:08:45 ART 2003
+ *
+ * $Id$
+ */
+
+/** \file
+ *
+ * Este es el archivo a incluir si se quieren usar las funciones personalizadas
+ * de malloc() y free().
+ */
+
+#ifndef MEMDEBUG_DEBUGGER_H
+#define MEMDEBUG_DEBUGGER_H
+
+#include "memdebug.h"
+
+#ifdef malloc
+#undef malloc
+#endif
+
+#ifdef free
+#undef free
+#endif
+
+/**
+ * Malloc personalizado.
+ * \see memdebug_malloc()
+ */
+#define malloc(b) memdebug_malloc(b, __FILE__, __LINE__)
+
+/**
+ * Free personalizado.
+ * \see memdebug_free()
+ */
+#define free(p) memdebug_free(p)
+
+#endif /* MEMDEBUG_DEBUGGER_H */
diff --git a/memdebug_test.c b/memdebug_test.c
new file mode 100644 (file)
index 0000000..b11e471
--- /dev/null
@@ -0,0 +1,55 @@
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: sáb ago 30 18:24:31 ART 2003
+ *
+ * $Id$
+ */
+
+/** \file
+ *
+ * Hace chequeos para probar el memdebugger.
+ */
+
+/* Para utilizar printf() */
+#include <stdio.h>
+/* Para utilizar EXIT_SUCCES */
+#include <stdlib.h>
+/* Para utilizar assert() */
+#include <assert.h>
+
+/* Para llamar al malloc() y free() personalizados. */
+#include "memdebug_debugger.h"
+
+/**
+ * Programa para probar el memdebug.
+ *
+ * \return EXIT_SUCCESS o código de error devuelto por abort() si hubo un
+ *         error.
+ */
+int main(void) {
+    /* Declaración de variables. */
+    void* ptr1 = malloc(1000);
+    void* ptr2 = malloc(1000);
+    void* ptr3 = malloc(1000);
+
+    memdebug_list_print(stderr);
+
+    fprintf(stderr, "\n");
+    
+    free(ptr1);
+    free(ptr2);
+    free(ptr3);
+
+    memdebug_end();
+
+    return EXIT_SUCCESS;
+}
diff --git a/meminfo.c b/meminfo.c
new file mode 100644 (file)
index 0000000..f0214f0
--- /dev/null
+++ b/meminfo.c
@@ -0,0 +1,45 @@
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: sáb ago 30 20:08:45 ART 2003
+ *
+ * $Id$
+ */
+
+#include "meminfo.h"
+#include <stdlib.h>
+#include <string.h>
+
+MemInfo* MemInfo_new(void* ptr, size_t bytes, const char* fname, size_t fline) {
+    /* Aloco memoria. */
+    MemInfo* mi = malloc(sizeof(MemInfo));
+    /* Si la obtuve, inicializo con los datos y la hora actual. */
+    if (mi) {
+        mi->pointer  = ptr;
+        mi->bytes    = bytes;
+        mi->time     = time(NULL);
+        mi->fileline = fline;
+        /* Reservo memoria para hacer la copia del nombre del archivo. */
+        mi->filename = (char*)malloc(strlen(fname));
+        /* Copio el nombre del archivo. */
+        strcpy(mi->filename, fname);
+    }
+    /* Devuelvo el nuevo puntero. */
+    return mi;
+}
+
+void MemInfo_delete(MemInfo* mi) {
+    /* Libero primero la memoria del nombre del archivo. */
+    free(mi->filename);
+    /* Libero la memoria del MemInfo. */
+    free(mi);
+}
+
index d013f92199478c21b34a00e1e88c24b0762893ea..f152d9f70adc55e42e1fe320f50e83b86b59af6a 100644 (file)
--- a/meminfo.h
+++ b/meminfo.h
 #ifndef MEMINFO_H
 #define MEMINFO_H
 
+#include <time.h>
+
 /**
- * Nodo de la lista.
+ * Información sobre la memoria.
  */
 typedef struct {
+    /** Puntero a la memoria reservada. */
     void*   pointer;
+    /** Cantidad de bytes reservados. */
     size_t  bytes;
+    /** Fecha en la que se reservó. */
     time_t  time;
+    /** Nombre del archivo de donde se reservó. */
     char*   filename;
+    /** Línea en la que se reservó. */
     size_t  fileline;
 } MemInfo;
 
-MemInfo* MemInfo_new(void* ptr, size_t bytes, char* fname, size_t fline) {
-    /* Aloco memoria. */
-    MemInfo* mi = (MemInfo*)malloc(sizeof(MemInfo));
-    /* Si la obtuve, inicializo con los datos y la hora actual. */
-    if (mi) {
-        mi->pointer  = ptr;
-        mi->bytes    = bytes;
-        mi->time     = time();
-        mi->filename = fname;
-        mi->fileline = fline;
-    }
-    /* Devuelvo el nuevo puntero. */
-    return mi;
-}
+/**
+ * Crea un nuevo MemInfo.
+ *
+ * \param ptr   Puntero a un área de memoria.
+ * \param bytes Cantidad de bytes reservados.
+ * \param fname Nombre del archivo de donde se reservó.
+ * \param fline Línea en donde se reservó.
+ *
+ * \return Puntero al nuevo MemInfo o NULL si no hay espacio en la memoria.
+ */
+MemInfo* MemInfo_new(void* ptr, size_t bytes, const char* fname, size_t fline);
+
+/**
+ * Elimina un MemInfo.
+ *
+ * \param mi MemInfo a eliminar.
+ */
+void MemInfo_delete(MemInfo* mi);
 
 #endif /* MEMINFO_H */