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
|
#include <stdlib.h>
#include <stdio.h>
#define WHEAP_RECORD_FLAG_INUSE 0
#define WHEAP_RECORD_FLAG_UNUSED 1
#define WHEAP_RECORD_FLAG_FREED 2
typedef struct WHEAP_RECORD
{
struct WHEAP_RECORD *next;
unsigned short flags, unused;
int size;
}
wHeapRecord;
#define WHEAP_PAD_START 0
#define WHEAP_PAD_END 0
#undef WHEAP_DO_PAD
#define WHEAP_RECORD_SIZE (sizeof(wHeapRecord))
#define WHEAP_PAD_SIZE ((WHEAP_PAD_START)+(WHEAP_PAD_END))
#define WHEAP_SIZE_CUTOFF ((WHEAP_RECORD_SIZE)+64)
static wHeapRecord *wHeapStart;
static wHeapRecord *wHeapFirst;
void heap_init (int size)
{
wHeapStart = (wHeapRecord *) malloc (size);
wHeapFirst = wHeapStart;
wHeapStart->flags = WHEAP_RECORD_FLAG_UNUSED;
wHeapStart->next = 0;
wHeapStart->size = size - sizeof (wHeapRecord);
}
void *Monmalloc (size_t size)
{
wHeapRecord *rec = wHeapFirst;
void *voidptr;
int n;
size = (size + 3) & (~3);
if (size == 0)
size = 4;
size += WHEAP_PAD_SIZE;
if (!rec)
{
fprintf (stderr, "wHeapAlloc: heap full!");
return 0;
} // should not happen given normal use.
while (rec->size < size)
{
fprintf (stderr, "ok1\n");
if (!rec->next)
{
fprintf (stderr, "wHeapAlloc: heap too full!");
return 0;
} // cannot alloc
if (rec->next->flags != WHEAP_RECORD_FLAG_INUSE)
{ // try to merge with next one
rec->size += rec->next->size + WHEAP_RECORD_SIZE;
rec->next = rec->next->next;
}
else
{ // skip ahead to more friendly waters
rec = rec->next;
while (rec->next)
{
if (rec->flags != WHEAP_RECORD_FLAG_INUSE)
break;
rec = rec->next;
}
if (rec->flags == WHEAP_RECORD_FLAG_INUSE)
{
fprintf (stderr, "wHeapAlloc: heap too full!");
return 0;
} // no empty slots :(
}
}
rec->flags = WHEAP_RECORD_FLAG_INUSE;
n = rec->size - size;
if (rec <= NULL)
fprintf (stderr, "rec null\n");
if (sizeof (wHeapRecord) == 0)
fprintf (stderr, "wHeapRecord = 0\n");
voidptr = ((char *) rec) + sizeof (wHeapRecord) + WHEAP_PAD_START;
if (n < WHEAP_SIZE_CUTOFF)
{ // pad to include unused portion
rec->unused = n;
}
else
{ // chop block into 2
wHeapRecord *rec2;
rec2 = (wHeapRecord *) (((char *) rec) + WHEAP_RECORD_SIZE + size);
rec2->flags = WHEAP_RECORD_FLAG_UNUSED;
rec2->size = rec->size - size - WHEAP_RECORD_SIZE;
rec->size = size;
rec2->next = rec->next;
rec->next = rec2;
rec->unused = 0;
}
if (rec == wHeapFirst)
{
while (wHeapFirst->next && wHeapFirst->flags == WHEAP_RECORD_FLAG_INUSE)
wHeapFirst = wHeapFirst->next;
if (wHeapFirst->flags == WHEAP_RECORD_FLAG_INUSE)
{
wHeapFirst = 0;
}
}
return voidptr;
}
void Monfree (void *data)
{
wHeapRecord *rec =
(wHeapRecord *) (((char *) data) - WHEAP_RECORD_SIZE - WHEAP_PAD_START);
if (rec->flags != WHEAP_RECORD_FLAG_INUSE)
{ // note heap error
fprintf (stderr, "wHeapFree: Data already freed! %p", data);
}
rec->flags = WHEAP_RECORD_FLAG_FREED;
if (rec < wHeapFirst || !wHeapFirst)
wHeapFirst = rec; // reposition the "starting" pointer.
}
#ifdef TEST
#include <string.h>
int main (void)
{
heap_init (64);
char *s = Monmalloc (52);
if (s != NULL)
{
strcpy (s, "hello world !");
puts (s);
Monfree (s), s = NULL;
}
return 0;
}
#endif |
Partager