4215
|
1 #include "config.h"
|
|
2 #include "main.h"
|
|
3 #include "xmalloc.h"
|
|
4
|
|
5 #include <assert.h>
|
|
6 #include <stdio.h>
|
|
7 #include <stdlib.h>
|
|
8 #include <string.h>
|
|
9 #include <errno.h>
|
|
10
|
|
11 #ifdef DEBUG_MALLOC
|
|
12 #define IF_DB(x) x
|
|
13 #else
|
|
14 #define IF_DB(x)
|
|
15 #endif
|
|
16
|
|
17 static struct node {
|
|
18 void *ptr;
|
|
19 struct node *prev, *next;
|
|
20 size_t size;
|
|
21 #if DEBUG_P
|
|
22 const char *file;
|
|
23 unsigned line;
|
|
24 #endif
|
|
25 } *Root;
|
|
26
|
|
27 #if 0
|
|
28 int xdump(void) {
|
|
29 struct node *p;
|
|
30
|
|
31 fprintf(stderr, ":%p\n", Root);
|
|
32 for (p = Root; p; p = p->next) {
|
|
33 fprintf(stderr, "\\<%p [%p]%p %p>\n", p->prev, p, p->ptr, p->next);
|
|
34 assert(p != p->next);
|
|
35 }
|
|
36 fprintf(stderr, "\n");
|
|
37 return 0;
|
|
38 }
|
|
39 #endif
|
|
40
|
|
41 void xend(void) {
|
|
42 struct node *p;
|
|
43
|
|
44 while ((p = Root)) {
|
|
45 #if DEBUG_P
|
|
46 unsigned char *ptr;
|
|
47 for (ptr = p->ptr; memcmp(ptr, &p, sizeof p); ++ptr)
|
|
48 ;
|
|
49 ptr += sizeof p;
|
|
50 fprintf(stderr, "%s: autofreeing pointer %p (%p) from %s:%u\n", Prog, p->ptr, (void *)ptr, p->file, p->line);
|
|
51 #else
|
|
52 fprintf(stderr, "%s: autofreeing pointer %p\n", Prog, p->ptr);
|
|
53 #endif
|
|
54 free(p->ptr);
|
|
55 assert(Root != p->next);
|
|
56 Root = p->next;
|
|
57 free(p);
|
|
58 }
|
|
59 }
|
|
60
|
|
61 #define XFACTOR(size) ((sizeof (struct node *) - 1) / (size) + 1u)
|
|
62
|
|
63 #if DEBUG_P
|
|
64 void *(xrealloc)(void *optr, size_t nmemb, const char *file, unsigned line) {
|
|
65 #else
|
|
66 void *xrealloc(void *optr, size_t nmemb) {
|
|
67 #endif
|
|
68 struct node *p;
|
|
69 size_t k;
|
|
70 size_t size;
|
|
71 unsigned char *r;
|
|
72 void *ptr;
|
|
73
|
|
74 assert(optr != NULL);
|
|
75
|
|
76 memcpy(&p, (unsigned char *)optr - sizeof Root, sizeof p);
|
|
77 size = p->size;
|
|
78 k = XFACTOR(size) * size;
|
|
79 if (!(ptr = realloc(p->ptr, size * nmemb + k))) {
|
|
80 fprintf(stderr, "%s: realloc(%p, %lu): %s\n", Prog, ptr, (unsigned long)(nmemb * size), strerror(errno));
|
|
81 abort();
|
|
82 }
|
|
83 r = (unsigned char *)ptr + k;
|
|
84 #if DEBUG_P
|
|
85 IF_DB(fprintf(stderr, "%s: xrealloc(%zu): %p (%p) from %s:%u -> %p (%p) from %s:%u\n", Prog, nmemb, p->ptr, optr, p->file, p->line, ptr, r, file, line));
|
|
86 p->file = file;
|
|
87 p->line = line;
|
|
88 #endif
|
|
89 p->ptr = ptr;
|
|
90 return r;
|
|
91 }
|
|
92
|
|
93 #if DEBUG_P
|
|
94 void *(xmalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {
|
|
95 #else
|
|
96 void *xmalloc(size_t nmemb, size_t size) {
|
|
97 #endif
|
|
98 struct node *p;
|
|
99 size_t k;
|
|
100 unsigned char *r;
|
|
101
|
|
102 if ((p = malloc(sizeof *p))) {
|
|
103 k = XFACTOR(size) * size;
|
|
104 if (!(p->ptr = malloc(size * nmemb + k))) {
|
|
105 free(p);
|
|
106 goto failure;
|
|
107 }
|
|
108 } else failure: {
|
|
109 fprintf(stderr, "%s: malloc(%lu): %s\n", Prog, (unsigned long)(nmemb * size), strerror(errno));
|
|
110 abort();
|
|
111 }
|
|
112 #if DEBUG_P
|
|
113 memset(p->ptr, 'U', k);
|
|
114 #endif
|
|
115 r = (unsigned char *)p->ptr + k;
|
|
116 memcpy(r - sizeof Root, &p, sizeof p);
|
|
117 p->size = size;
|
|
118 p->prev = NULL;
|
|
119 p->next = Root;
|
|
120 #if DEBUG_P
|
|
121 p->file = file;
|
|
122 p->line = line;
|
|
123 IF_DB(fprintf(stderr, "%s: xmalloc(%zu, %zu): %p (%p) from %s:%u\n", Prog, nmemb, size, p->ptr, r, file, line));
|
|
124 #endif
|
|
125 if (Root) {
|
|
126 Root->prev = p;
|
|
127 }
|
|
128 Root = p;
|
|
129 return r;
|
|
130 }
|
|
131
|
|
132 #if 0
|
|
133 #if DEBUG_P
|
|
134 void *(xcalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {
|
|
135 void *const p = xmalloc(nmemb, size, file, line);
|
|
136 #else
|
|
137 void *xcalloc(size_t nmemb, size_t size) {
|
|
138 void *const p = xmalloc(nmemb, size);
|
|
139 #endif
|
|
140 memset(p, '\0', nmemb * size);
|
|
141 return p;
|
|
142 }
|
|
143 #endif
|
|
144
|
|
145 void xfree(void *ptr) {
|
|
146 struct node *p;
|
|
147
|
|
148 if (!ptr)
|
|
149 return;
|
|
150 memcpy(&p, (unsigned char *)ptr - sizeof Root, sizeof p);
|
|
151 assert(p != NULL);
|
|
152 DEBUG(memset((unsigned char *)ptr - sizeof Root, 'F', sizeof Root));
|
|
153
|
|
154 if (p->next) {
|
|
155 p->next->prev = p->prev;
|
|
156 }
|
|
157 if (p->prev) {
|
|
158 p->prev->next = p->next;
|
|
159 } else {
|
|
160 assert(p == Root);
|
|
161 Root = Root->next;
|
|
162 }
|
|
163 #if DEBUG_P
|
|
164 IF_DB(fprintf(stderr, "%s: xfree(): %p (%p) from %s:%u\n", Prog, p->ptr, ptr, p->file, p->line));
|
|
165 #endif
|
|
166 free(p->ptr);
|
|
167 free(p);
|
|
168 }
|