]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - memdebug.c
Se mejora la salida del memdebug y se hace que solo imprima la memoria alocada a
[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 | %-30s | %-20s | %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, "+------------+-------+--------------------------------+"
60             "----------------------+-------+\n");
61     fprintf(fp, "| %-10s | %-5s | %-30s | %-20s | %-5s |\n",
62             "Ptr",
63             "Bytes",
64             "Fecha",
65             "Archivo",
66             "Línea");
67     fprintf(fp, "+------------+-------+--------------------------------+"
68             "----------------------+-------+\n");
69     for (mi = DLList_begin(memdebug_list);
70             DLList_have_more(memdebug_list);
71             mi = DLList_next(memdebug_list)) {
72         memdebug_info_print(mi, fp);
73     }
74     fprintf(fp, "+------------+-------+--------------------------------+"
75             "----------------------+-------+\n");
76 }
77
78 void* memdebug_malloc(size_t bytes, const char* fname, size_t fline) {
79     void* ptr;
80     /* Si no está creada la lista global, la creo (o intento). */
81     if (!memdebug_list) {
82         memdebug_list = DLList_new();
83         /* Si no se puede crear la lista no reservo memoria, devuelvo NULL. */
84         if (!memdebug_list) {
85 #ifdef DEBUG
86             fprintf(stderr, "%s: No se pudo crear la lista interna "
87                             "(llamado desde %s, línea %i).\n",
88                     __FILE__, fname, fline);
89 #endif
90             return NULL;
91         }
92     }
93     /* Intento reservar memoria pedida. */
94     ptr = malloc(bytes);
95     /* Si se puedo reservar, creo un nuevo nodo y lo agrego a la lista. */
96     if (ptr) {
97         MemInfo* mi = MemInfo_new(ptr, bytes, fname, fline);
98         /* Si no se puede crear el nodo, devuelvo NULL. */
99         if (!mi || !DLList_push(memdebug_list, mi)) {
100 #ifdef DEBUG
101             fprintf(stderr, "%s: No se pudo crear el nodo para 0x%X "
102                             "(llamado desde %s, línea %u).\n",
103                     __FILE__, (size_t)ptr, fname, fline);
104 #endif
105             return NULL;
106         }
107     }
108     return ptr;
109 }
110
111 void memdebug_free(void* ptr) {
112     /* Busca en la lista y de encontrarlo nos lo deja en el elemento actual. */
113     if (memdebug_DLList_find(memdebug_list, ptr)) {
114         /* Lo encontró, elimino el nodo actual. */
115         DLList_remove_current(memdebug_list);
116 #ifdef DEBUG
117     } else {
118         fprintf(stderr, "%s: No se encontro el ptr 0x%X en la lista.\n",
119                 __FILE__, (size_t)ptr);
120 #endif
121     }
122     /* Lo encuentre o no, trata de liberar la memoria. */
123     free(ptr);
124 }
125
126 void memdebug_end(void) {
127     /* Si hay una lista. */
128     if (memdebug_list) {
129         MemInfo* mi;
130         /* Imprimo la lista si hay algun elemento. */
131         if (!DLList_empty(memdebug_list)) {
132             memdebug_list_print(stderr);
133         }
134         /* Libero la memoria de cada elemento y cada puntero almacenado. */
135         while (!DLList_empty(memdebug_list)) {
136             mi = DLList_pop(memdebug_list);
137             free(mi->pointer);
138             MemInfo_delete(mi);
139         }
140     }
141 }
142