]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - memdebug.c
Se termina el malloc debugger, incluyendo un test simple (falta documentar).
[z.facultad/75.42/calculadora.git] / memdebug.c
1 /* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
2  *
3  * Taller de Programación (75.42).
4  *
5  * Ejercicio Número 2:
6  * Programa calculadora.
7  *
8  * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
9  * Puede copiar, modificar y distribuir este programa bajo los términos de
10  * la licencia GPL (http://www.gnu.org/).
11  *
12  * Creado: sáb ago 30 20:08:45 ART 2003
13  *
14  * $Id$
15  */
16
17 #include "memdebug.h"
18 #include "dllist.h"
19 #include "meminfo.h"
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 /**
25  * Lista interna a utilizar en memdebug_malloc() y memdebug_free().
26  */
27 static DLList* memdebug_list;
28
29 /**
30  * FIXME la búsqueda se realiza de atrás hacia adelante para que sea más
31  * eficiente, ya que generalmente se borra primero la memoria que se pidió
32  * úitima.
33  */
34 bool memdebug_DLList_find(DLList* list, void* ptr) {
35     MemInfo* i;
36     for (i = DLList_end(list); DLList_have_more(list); i = DLList_prev(list)) {
37         if (i->pointer == ptr) {
38             return TRUE;
39         }
40     }
41     return FALSE;
42 }
43
44 void memdebug_info_print(MemInfo* mi, FILE* fp) {
45     char fecha[30];
46     struct tm* ltime;
47     ltime = localtime(&(mi->time));
48     strftime(fecha, 30, "%c", ltime);
49     fprintf(fp, "0x%08X | %5u | %-25s | %-16s | %5u\n",
50             (size_t)(mi->pointer),
51             mi->bytes,
52             fecha,
53             mi->filename,
54             mi->fileline);
55 }
56
57 void memdebug_list_print(FILE* fp) {
58     MemInfo* mi;
59     fprintf(fp, "%-10s | %-5s | %-25s | %-16s | %-5s\n",
60             "Ptr",
61             "Bytes",
62             "Fecha",
63             "Archivo",
64             "Línea");
65     fprintf(fp, "-----------+-------+---------------------------+"
66             "------------------+------\n");
67     for (mi = DLList_begin(memdebug_list);
68             DLList_have_more(memdebug_list);
69             mi = DLList_next(memdebug_list)) {
70         memdebug_info_print(mi, fp);
71     }
72 }
73
74 void* memdebug_malloc(size_t bytes, const char* fname, size_t fline) {
75     void* ptr;
76     /* Si no está creada la lista global, la creo (o intento). */
77     if (!memdebug_list) {
78         memdebug_list = DLList_new();
79         /* Si no se puede crear la lista no reservo memoria, devuelvo NULL. */
80         if (!memdebug_list) {
81 #ifdef DEBUG
82             fprintf(stderr, "%s: No se pudo crear la lista interna "
83                             "(llamado desde %s, línea %i).\n",
84                     __FILE__, fname, fline);
85 #endif
86             return NULL;
87         }
88     }
89     /* Intento reservar memoria pedida. */
90     ptr = malloc(bytes);
91     /* Si se puedo reservar, creo un nuevo nodo y lo agrego a la lista. */
92     if (ptr) {
93         MemInfo* mi = MemInfo_new(ptr, bytes, fname, fline);
94         /* Si no se puede crear el nodo, devuelvo NULL. */
95         if (!mi || !DLList_push(memdebug_list, mi)) {
96 #ifdef DEBUG
97             fprintf(stderr, "%s: No se pudo crear el nodo para 0x%X "
98                             "(llamado desde %s, línea %u).\n",
99                     __FILE__, (size_t)ptr, fname, fline);
100 #endif
101             return NULL;
102         }
103     }
104     return ptr;
105 }
106
107 void memdebug_free(void* ptr) {
108     /* Busca en la lista y de encontrarlo nos lo deja en el elemento actual. */
109     if (memdebug_DLList_find(memdebug_list, ptr)) {
110         /* Lo encontró, elimino el nodo actual. */
111         DLList_remove_current(memdebug_list);
112 #ifdef DEBUG
113     } else {
114         fprintf(stderr, "%s: No se encontro el ptr 0x%X en la lista.\n",
115                 __FILE__, (size_t)ptr);
116 #endif
117     }
118     /* Lo encuentre o no, trata de liberar la memoria. */
119     free(ptr);
120 }
121
122 void memdebug_end(void) {
123     /* Si hay una lista. */
124     if (memdebug_list) {
125         MemInfo* mi;
126         /* Imprimo la lista. */
127         memdebug_list_print(stderr);
128         /* Libero la memoria de cada elemento y cada puntero almacenado. */
129         while (!DLList_empty(memdebug_list)) {
130             mi = DLList_pop(memdebug_list);
131             free(mi->pointer);
132             MemInfo_delete(mi);
133         }
134     }
135 }
136