1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/* cmalloc.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cmalloc.h"
/* Allocate memory and check if anything was actually allocated.
If not, print an error message or do something else */
static void std_alloc_fail(void)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
static void (*alloc_fail)(void) = std_alloc_fail;
/* Also does a few checks that the library functions should already do */
/*
0 = don't check at all
1 = try to fix errors without telling
2 = warn about errors and try to fix them
3 = warn about errors and fail
*/
static int paranoia = 1;
typedef struct malloc_node {
void *p; /* allocated memory */
struct malloc_node *next; /* next in chain */
} malloc_node;
malloc_node *nodes = NULL;
static void remove_node(void *p)
{
malloc_node *m, *n;
if (!p) return; /* deallocating NULL is fine */
n = nodes;
if (!n) {
if (paranoia == 1) return;
fprintf(stderr,
"Deallocating %p when nothing allocated\n", p);
if (paranoia == 2) return;
alloc_fail();
}
if (n->p == p) {
nodes = n->next;
free(n);
return;
}
for (m = n->next; m; m = m->next) {
if (m->p == p) {
n->next = m->next;
free(m);
return;
}
n = m;
}
if (paranoia == 1) return;
fprintf(stderr, "Deallocating %p which was not allocated\n", p);
if (paranoia == 2) return;
alloc_fail();
}
static void insert_node(void *p)
{
malloc_node *n;
if (!p) return; /* we don't need to remember NULL */
n = malloc(sizeof(malloc_node));
if (n == NULL) alloc_fail();
n->p = p;
n->next = nodes;
nodes = n;
}
void cmalloc_init(void (*new_fail)(void), int level)
{
if (new_fail) alloc_fail = new_fail;
else alloc_fail = std_alloc_fail;
paranoia = level;
}
void cmalloc_exit(void)
{
malloc_node *n;
if (paranoia == 0) return;
for (n = nodes; n; n = n->next) {
if (paranoia >= 2)
fprintf(stderr, "Didn't deallocate %p\n", n->p);
if (paranoia == 3) alloc_fail();
cfree(n->p);
}
}
void *cmalloc(size_t size)
{
void *p;
p = malloc(size);
if (p == NULL) alloc_fail();
if (paranoia) insert_node(p);
return p;
}
void *crealloc(void *ptr, size_t size)
{
void *p;
if (paranoia) remove_node(ptr);
p = realloc(ptr, size);
if (p == NULL) alloc_fail();
if (paranoia) insert_node(p);
return p;
}
void *ccalloc(size_t nmemb, size_t size)
{
void *p;
p = calloc(nmemb, size);
if (p == NULL) alloc_fail();
if (paranoia) insert_node(p);
return p;
}
char *cstrdup(const char *s)
{
char *p;
if (s) p = malloc(strlen(s)+1);
else p = NULL;
if (p == NULL) alloc_fail();
else strcpy(p, s);
if (paranoia) insert_node(p);
return p;
}
void cfree(void *ptr)
{
if (paranoia) remove_node(ptr);
free(ptr);
}
|