-
Notifications
You must be signed in to change notification settings - Fork 0
/
memchk.c
138 lines (124 loc) · 3.62 KB
/
memchk.c
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
#include <stdlib.h>
#include <string.h>
#include "assert.h"
#include "except.h"
#include <stdint.h>
#include "mem.h"
union align {
int32_t i;
long l;
long* lp;
void* p;
void (*fp)(void);
float f;
double d;
long double ld;
};
#define hash(p,t) (((unsigned long)(p)>>3) & \
(sizeof(t)/sizeof((t)[0])-1))
#define NDESCRIPTORS 512
#define NALLOC ((4096+sizeof(union align)-1)/ \
(sizeof(union align)))*(sizeof(union align))
const Except_T Mem_Failed = {"Allocation Failed"};
static struct descriptor{
struct descriptor *free;
struct descriptor *link;
const void *ptr;
long size;
const char *file;
int32_t line;
}*htab[2048];
static struct descriptor freelist = { &freelist };
static struct descriptor *find(const void *ptr){
struct descriptor *bp = htab[hash(ptr,htab)];
while(bp && bp->ptr != ptr) bp=bp->link;
return bp;
}
void Mem_free(void* ptr, const char* file, int32_t line){
if(ptr){
struct descriptor *bp;
bp=NULL;
if(((unsigned long)ptr)%(sizeof(union align)) !=0 || (bp=find(ptr))==NULL ||bp->free){
Except_raise(&Assert_Failed,file,line);
}
bp->free = freelist.free;
freelist.free=bp;
}
}
void* Mem_resize(void* ptr, long nbytes, const char* file, int32_t line){
struct descriptor *bp;
void *newptr;
newptr=NULL;
bp=NULL;
assert(ptr);
assert(nbytes>0);
if(((unsigned long)ptr)%(sizeof(union align)) !=0 || (bp=find(ptr))==NULL ||bp->free){
Except_raise(&Assert_Failed,file,line);
}
newptr = Mem_alloc(nbytes,file,line);
memcpy(newptr,ptr,nbytes < bp->size ? nbytes: bp->size);
Mem_free(ptr,file,line);
return newptr;
}
void *Mem_calloc(long count,long nbytes, const char* file, int32_t line){
void *ptr;
assert(count > 0);
assert(nbytes > 0);
ptr=Mem_alloc(count*nbytes,file,line);
memset(ptr,'\0',count*nbytes);
return ptr;
}
static struct descriptor *dalloc(void* ptr,long size, const char *file, int32_t line){
static struct descriptor *avail;
static int32_t nleft;
if(nleft <=0){
avail = malloc(NDESCRIPTORS*sizeof(*avail));
if(avail == NULL) return NULL;
nleft = NDESCRIPTORS;
}
avail->ptr = ptr;
avail->size = size;
avail->file = file;
avail->line = line;
avail->free = avail->link = NULL;
nleft--;
return avail++;
}
void *Mem_alloc(long nbytes, const char *file, int32_t line){
struct descriptor *bp;
void *ptr;
assert(nbytes > 0);
nbytes = ((nbytes+sizeof(union align)-1)/sizeof(union align))*(sizeof(union align));
for(bp=freelist.free; bp; bp=bp->free){
if(bp->size > nbytes){
bp->size -= nbytes;
ptr = (char*)bp->ptr + bp->size;
if((bp=dalloc(ptr,nbytes,file,line))!=NULL){
unsigned h = hash(ptr,htab);
bp->link = htab[h];
htab[h] = bp;
return ptr;
}
else{
if(file==NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed,file,line);
}
}
if(bp == &freelist){
struct descriptor *newptr;
newptr=NULL;
if((ptr = malloc(nbytes+NALLOC))== NULL || (newptr=dalloc(ptr,nbytes+NALLOC, __FILE__, __LINE__))==NULL){
if(file==NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed,file,line);
}
newptr->free=freelist.free;
freelist.free = newptr;
}
}
assert(0);
return NULL;
}