Fixed runtime errors.
This commit is contained in:
parent
7464c85692
commit
6e9c27b71e
@ -6,12 +6,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
#define ALIGN4(s) (((((s)-1)>>2)<<2)+4)
|
|
||||||
#define ALIGN16(s) (((s) + 15) & ~0x0F)
|
|
||||||
#define ALIGNMENT 4
|
|
||||||
#define BLOCK_SIZE sizeof(struct Block)
|
|
||||||
#define MINIMUM_BLOCK_SIZE (sizeof(struct Block) + 16)
|
|
||||||
|
|
||||||
enum MemMode : unsigned char
|
enum MemMode : unsigned char
|
||||||
{
|
{
|
||||||
MEM_MODE_SPEED, // Memory will be allocated more quickly but loses memory efficiency.
|
MEM_MODE_SPEED, // Memory will be allocated more quickly but loses memory efficiency.
|
||||||
@ -34,9 +28,10 @@ void *realloc(void *ptr, size_t newSize);
|
|||||||
/// @param [in] ptr The memory to flag as free.
|
/// @param [in] ptr The memory to flag as free.
|
||||||
void free(void *ptr);
|
void free(void *ptr);
|
||||||
|
|
||||||
|
size_t get_header_size();
|
||||||
|
|
||||||
/// Will retrieve the current real byte size of the heap.
|
/// Will retrieve the current real byte size of the heap.
|
||||||
/// @returns The size in bytes.
|
/// @returns The size in bytes.
|
||||||
size_t get_heap_size();
|
size_t get_heap_size();
|
||||||
|
|
||||||
/// Will check memory blocks on program exit if there's dangling memory.
|
void cleanup_memory();
|
||||||
void check_memory();
|
|
187
src/CHM.c
187
src/CHM.c
@ -6,6 +6,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#define ALIGN4(s) (((((s)-1)>>2)<<2)+4)
|
||||||
|
#define ALIGN16(s) (((s) + 15) & ~0x0F)
|
||||||
|
#define ALIGNMENT 4
|
||||||
|
#define BLOCK_SIZE sizeof(struct Block)
|
||||||
|
|
||||||
/// The memory block's header.
|
/// The memory block's header.
|
||||||
struct Block
|
struct Block
|
||||||
{
|
{
|
||||||
@ -25,7 +30,7 @@ void set_memory_mode(const enum MemMode new_mode)
|
|||||||
{
|
{
|
||||||
if (new_mode > MEM_MODE_BALANCED)
|
if (new_mode > MEM_MODE_BALANCED)
|
||||||
{
|
{
|
||||||
printf("The given memory mode, \"%i\", is invalid.", new_mode);
|
fprintf(stderr, "The given memory mode, \"%i\", is invalid.", new_mode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,61 +67,6 @@ struct Block *extend_heap(const size_t s)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Block *extend_block(struct Block *in, const size_t newSize)
|
|
||||||
{
|
|
||||||
if (!in->next)
|
|
||||||
{
|
|
||||||
void *addr = (struct Block *)syscall(SYS_brk, NULL);
|
|
||||||
|
|
||||||
if ((void *)syscall(SYS_brk, (char *)addr + (newSize - in->size)) == (void *)-1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
in->size = newSize;
|
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t totalSize = in->size;
|
|
||||||
struct Block *start = in->prev;
|
|
||||||
struct Block *end = in->next;
|
|
||||||
|
|
||||||
while (start && start->free && totalSize < newSize)
|
|
||||||
{
|
|
||||||
totalSize += BLOCK_SIZE + in->prev->size;
|
|
||||||
start = in->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (end && end->free && totalSize < newSize)
|
|
||||||
{
|
|
||||||
totalSize += BLOCK_SIZE + end->size;
|
|
||||||
end = end->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalSize < newSize || (mode == MEM_MODE_EFFICIENCY && totalSize > newSize))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!start)
|
|
||||||
start = in;
|
|
||||||
|
|
||||||
if (!end)
|
|
||||||
end = in;
|
|
||||||
|
|
||||||
struct Block *b = start->next;
|
|
||||||
while (b)
|
|
||||||
{
|
|
||||||
start->size += BLOCK_SIZE + b->size;
|
|
||||||
b = b->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
start->next = end->next;
|
|
||||||
start->free = 0;
|
|
||||||
|
|
||||||
if (!start->next)
|
|
||||||
last = start;
|
|
||||||
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Will defragment adjacent memory blocks of the given memory block.
|
/// Will defragment adjacent memory blocks of the given memory block.
|
||||||
/// @param [in] in The memory block to defragment for.
|
/// @param [in] in The memory block to defragment for.
|
||||||
void defragment_adjacent_blocks(struct Block *in)
|
void defragment_adjacent_blocks(struct Block *in)
|
||||||
@ -151,6 +101,76 @@ void fragment_block(struct Block *in, size_t s)
|
|||||||
in->free = 0;
|
in->free = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Block *extend_block(struct Block *in, const size_t newSize)
|
||||||
|
{
|
||||||
|
if (!in->next)
|
||||||
|
{
|
||||||
|
void *addr = (struct Block *)syscall(SYS_brk, NULL);
|
||||||
|
|
||||||
|
if ((void *)syscall(SYS_brk, (char *)addr + (newSize - in->size)) == (void *)-1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
in->size = newSize;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t totalSize = in->size;
|
||||||
|
struct Block *start = in->prev;
|
||||||
|
struct Block *end = in->next;
|
||||||
|
|
||||||
|
while (start && start->free && totalSize < newSize)
|
||||||
|
{
|
||||||
|
totalSize += BLOCK_SIZE + start->size;
|
||||||
|
if (totalSize >= newSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
start = in->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (end && end->free && totalSize < newSize)
|
||||||
|
{
|
||||||
|
totalSize += BLOCK_SIZE + end->size;
|
||||||
|
if (totalSize >= newSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
end = end->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalSize < newSize || (mode == MEM_MODE_EFFICIENCY && totalSize > newSize))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!start)
|
||||||
|
start = in;
|
||||||
|
|
||||||
|
if (!end)
|
||||||
|
end = in;
|
||||||
|
|
||||||
|
struct Block *b = start->next;
|
||||||
|
while (b)
|
||||||
|
{
|
||||||
|
start->size += BLOCK_SIZE + b->size;
|
||||||
|
|
||||||
|
if (b == end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
start->next = end->next;
|
||||||
|
start->free = 0;
|
||||||
|
start->next->prev = start;
|
||||||
|
|
||||||
|
if (!start->next)
|
||||||
|
last = start;
|
||||||
|
|
||||||
|
const size_t remainder = start->size - (BLOCK_SIZE + newSize);
|
||||||
|
if (remainder && !(remainder % ALIGNMENT))
|
||||||
|
fragment_block(start, newSize);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds the first block that will fit the given size.
|
/// Finds the first block that will fit the given size.
|
||||||
/// @param [in] s The memory aligned size to look for.
|
/// @param [in] s The memory aligned size to look for.
|
||||||
/// @returns The matching available memory block.
|
/// @returns The matching available memory block.
|
||||||
@ -194,7 +214,7 @@ struct Block *find_balanced(const size_t s)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
const size_t remainder = current->size - totalSize;
|
const size_t remainder = current->size - totalSize;
|
||||||
if (!(remainder % ALIGNMENT))
|
if (remainder && !(remainder % ALIGNMENT))
|
||||||
{
|
{
|
||||||
fragment_block(current, s);
|
fragment_block(current, s);
|
||||||
break;
|
break;
|
||||||
@ -231,9 +251,10 @@ struct Block *find_best_fit(const size_t s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t remainder = current->size - totalSize;
|
||||||
if (best)
|
if (best)
|
||||||
{
|
{
|
||||||
if (current->size < best->size && !((current->size - totalSize) % ALIGNMENT))
|
if (current->size < best->size && remainder && !(remainder % ALIGNMENT))
|
||||||
{
|
{
|
||||||
fragment = 1;
|
fragment = 1;
|
||||||
best = current;
|
best = current;
|
||||||
@ -241,7 +262,7 @@ struct Block *find_best_fit(const size_t s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!((current->size - totalSize) % ALIGNMENT))
|
if (remainder && !(remainder % ALIGNMENT))
|
||||||
{
|
{
|
||||||
fragment = 1;
|
fragment = 1;
|
||||||
best = current;
|
best = current;
|
||||||
@ -311,22 +332,30 @@ void *realloc(void *ptr, size_t newSize)
|
|||||||
|
|
||||||
newSize = ALIGN16(newSize);
|
newSize = ALIGN16(newSize);
|
||||||
|
|
||||||
struct Block *b = ((struct Block *)ptr) - 1;
|
struct Block *b = (struct Block *)ptr - 1;
|
||||||
if (b->free)
|
if (b->free)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
size_t totalSize = BLOCK_SIZE + newSize;
|
if (b->size == newSize)
|
||||||
size_t remainder = b->size - totalSize;
|
return b + 1;
|
||||||
|
|
||||||
if (b->size < newSize && !extend_block(b, newSize))
|
const size_t totalSize = BLOCK_SIZE + newSize;
|
||||||
|
const size_t remainder = b->size - totalSize;
|
||||||
|
if (b->size < newSize) // Expand memory block if possible.
|
||||||
|
{
|
||||||
|
if (!extend_block(b, newSize))
|
||||||
return NULL;
|
return NULL;
|
||||||
else if (b->size > newSize && !(remainder % ALIGNMENT))
|
|
||||||
fragment_block(b, newSize);
|
|
||||||
else
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
return b + 1;
|
return b + 1;
|
||||||
}
|
}
|
||||||
|
else if (b->size > newSize && remainder && !(remainder % ALIGNMENT)) // Shrink memory block if possible.
|
||||||
|
{
|
||||||
|
fragment_block(b, newSize);
|
||||||
|
return b + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void free(void *ptr)
|
void free(void *ptr)
|
||||||
{
|
{
|
||||||
@ -359,27 +388,39 @@ void free(void *ptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t get_header_size()
|
||||||
|
{
|
||||||
|
return BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
size_t get_heap_size()
|
size_t get_heap_size()
|
||||||
{
|
{
|
||||||
if (!first || !last)
|
if (!first || !last)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (char*)first - (char*)last - last->size;
|
return (char*)last + last->size - (char*)first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_memory()
|
void cleanup_memory()
|
||||||
{
|
{
|
||||||
if (!first || !last)
|
if (!first || !last)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const struct Block *l = last;
|
||||||
struct Block *current = first;
|
struct Block *current = first;
|
||||||
while (current)
|
while (current)
|
||||||
{
|
{
|
||||||
if (current->free)
|
if (!current->free)
|
||||||
printf("Memory at the address %p has been marked free, but still persists.", current + 1);
|
fprintf(stderr, "Memory at the address %p has not been marked free. Possible memory leak?\n", current + 1);
|
||||||
else
|
|
||||||
printf("Memory at the address %p has not been marked free. Possible memory leak?", current + 1);
|
if (current == l)
|
||||||
|
break;
|
||||||
|
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syscall(SYS_brk, first);
|
||||||
|
|
||||||
|
first = NULL;
|
||||||
|
last = NULL;
|
||||||
}
|
}
|
18
src/main.c
18
src/main.c
@ -1,23 +1,25 @@
|
|||||||
#include "CHM.h"
|
#include "CHM.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
set_memory_mode(MEM_MODE_BALANCED);
|
||||||
|
|
||||||
int *a = (int *)malloc(sizeof(int));
|
int *a = (int *)malloc(sizeof(int));
|
||||||
|
*a = 1;
|
||||||
int *b = (int *)malloc(sizeof(int));
|
int *b = (int *)malloc(sizeof(int));
|
||||||
|
*b = 2;
|
||||||
|
int *c = (int *)malloc(sizeof(int));
|
||||||
|
*c = 3;
|
||||||
|
|
||||||
*a = 5;
|
|
||||||
*b = 12;
|
|
||||||
|
|
||||||
printf("Test 1: %i\n", *a);
|
|
||||||
printf("Test 2: %i\n", *b);
|
|
||||||
printf("Heap Size: %zu Bytes\n", get_heap_size());
|
printf("Heap Size: %zu Bytes\n", get_heap_size());
|
||||||
|
|
||||||
free(a);
|
free(a);
|
||||||
free(b);
|
free(b);
|
||||||
|
free(c);
|
||||||
|
|
||||||
int *c = (int *)malloc(sizeof(int));
|
cleanup_memory();
|
||||||
|
|
||||||
check_memory();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user