Fixes a lot of memory leaks. Adds malloc monitoring.

This commit is contained in:
Felix Queissner 2015-08-17 20:04:14 +02:00
parent 90eb432c50
commit 19c75d5fe9
12 changed files with 210 additions and 77 deletions

View file

@ -37,3 +37,7 @@ obj/main.o: scripts/main.ts
.PHONY: run
run:
qemu-system-i386 -serial stdio -kernel kernel
.PHONY: debug
debug:
qemu-system-i386 -s -S -serial stdio -kernel kernel

View file

@ -34,12 +34,12 @@ kernel: obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/s
# src/console.c
obj/console.o: src/console.c include/console.h include/stdlib.h \
include/varargs.h include/config.h
include/varargs.h include/config.h include/malloc.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/console.c
# src/init.c
obj/init.o: src/init.c include/kernel.h include/stdlib.h include/varargs.h \
include/config.h include/console.h include/interrupts.h \
include/config.h include/malloc.h include/console.h include/interrupts.h \
include/cpustate.h include/pmm.h include/multiboot.h include/vmm.h \
include/timer.h include/serial.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/init.c
@ -47,27 +47,29 @@ obj/init.o: src/init.c include/kernel.h include/stdlib.h include/varargs.h \
# src/interrupts.c
obj/interrupts.o: src/interrupts.c include/interrupts.h include/cpustate.h \
include/console.h include/stdlib.h include/varargs.h include/config.h \
include/io.h src/intr_stubs.h
include/malloc.h include/io.h src/intr_stubs.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/interrupts.c
# src/malloc.c
obj/malloc.o: src/malloc.c include/kernel.h include/stdlib.h \
include/varargs.h include/config.h include/console.h include/serial.h
include/varargs.h include/config.h include/malloc.h include/console.h \
include/serial.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/malloc.c
# src/pmm.c
obj/pmm.o: src/pmm.c include/pmm.h include/multiboot.h include/kernel.h \
include/stdlib.h include/varargs.h include/config.h include/console.h
include/stdlib.h include/varargs.h include/config.h include/malloc.h \
include/console.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/pmm.c
# src/serial.c
obj/serial.o: src/serial.c include/io.h include/serial.h include/stdlib.h \
include/varargs.h include/config.h
include/varargs.h include/config.h include/malloc.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/serial.c
# src/stdlib.c
obj/stdlib.o: src/stdlib.c include/stdlib.h include/varargs.h \
include/config.h include/kernel.h
include/config.h include/malloc.h include/kernel.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/stdlib.c
# src/timer.c
@ -77,13 +79,13 @@ obj/timer.o: src/timer.c include/timer.h include/kernel.h \
# src/vmm.c
obj/vmm.o: src/vmm.c include/config.h include/vmm.h include/pmm.h \
include/multiboot.h include/stdlib.h include/varargs.h include/console.h \
include/kernel.h
include/multiboot.h include/stdlib.h include/varargs.h include/malloc.h \
include/console.h include/kernel.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/vmm.c
# trainscript/tsvm.cpp
obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \
include/config.h include/console.h trainscript/common.h \
include/config.h include/malloc.h include/console.h trainscript/common.h \
trainscript/tsvm.hpp include/ker/string.hpp include/ker/vector.hpp \
include/ker/new.hpp include/ker/dictionary.hpp include/kernel.h \
include/ker/pair.hpp trainscript/typeid.hpp \
@ -93,29 +95,29 @@ obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \
# src/cplusplus.cpp
obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \
include/config.h include/console.h include/ker/new.hpp
include/config.h include/malloc.h include/console.h include/ker/new.hpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/cplusplus.cpp
# src/vm.cpp
obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h include/config.h \
include/timer.h include/dynamic.h src/../trainscript/tsvm.hpp \
include/console.h include/ker/string.hpp include/ker/vector.hpp \
include/ker/new.hpp include/ker/dictionary.hpp include/kernel.h \
include/ker/pair.hpp src/../trainscript/typeid.hpp
include/malloc.h include/timer.h include/dynamic.h \
src/../trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
include/kernel.h include/ker/pair.hpp src/../trainscript/typeid.hpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
# obj/trainscript.yy.cpp
obj/trainscript.yy.o: obj/trainscript.yy.cpp include/string.h \
include/stdlib.h include/varargs.h include/config.h trainscript/common.h \
trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
include/kernel.h include/ker/pair.hpp trainscript/typeid.hpp \
obj/trainscript.tab.hpp
include/stdlib.h include/varargs.h include/config.h include/malloc.h \
trainscript/common.h trainscript/tsvm.hpp include/console.h \
include/ker/string.hpp include/ker/vector.hpp include/ker/new.hpp \
include/ker/dictionary.hpp include/kernel.h include/ker/pair.hpp \
trainscript/typeid.hpp obj/trainscript.tab.hpp
$(CXX) -iquotetrainscript $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.yy.cpp
# obj/trainscript.tab.cpp
obj/trainscript.tab.o: obj/trainscript.tab.cpp include/stdlib.h \
include/varargs.h include/config.h trainscript/common.h \
include/varargs.h include/config.h include/malloc.h trainscript/common.h \
trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
include/kernel.h include/ker/pair.hpp trainscript/typeid.hpp \
@ -158,3 +160,7 @@ obj/main.o: scripts/main.ts
.PHONY: run
run:
qemu-system-i386 -serial stdio -kernel kernel
.PHONY: debug
debug:
qemu-system-i386 -s -S -serial stdio -kernel kernel

View file

@ -15,3 +15,7 @@
//*
#define USE_MAGIC_SECURED_MALLOC
//*/
//*
#define ENABLE_MALLOC_MONITORING
//*/

View file

@ -136,7 +136,7 @@ namespace ker
void copyFrom(const uint8_t *bytes, size_t length)
{
if(this->mText != nullptr) {
// free(this->mText);
free(this->mText);
}
this->mText = (uint8_t*)malloc(length + 1);
memcpy(this->mText, bytes, length);

View file

@ -66,6 +66,9 @@ namespace ker
~Vector()
{
if(this->mData != nullptr) {
for(size_t i = 0; i < this->mLength; i++) {
this->mData[i].~T();
}
free(this->mData);
}
}

60
include/malloc.h Normal file
View file

@ -0,0 +1,60 @@
#pragma once
#include <stddef.h>
#include <inttypes.h>
#include "config.h"
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(USE_VERBOSE_MALLOC)
void *malloc_d(size_t,const char *,int);
#endif
#if defined(USE_VERBOSE_FREE)
void free_d(void *,const char*, int);
#endif
#if defined(ENABLE_MALLOC_MONITORING)
void *_malloc(size_t, const char *, int);
void* _realloc (void*, size_t, const char *, int);
#define malloc(size) _malloc((size), __FILE__, __LINE__)
#define realloc(ptr, size) _realloc((ptr), (size), __FILE__, __LINE__)
#else
/**
* Allocates a block of memory
* @param size Minimum size of the memory block
* @return Pointer to the allocated memory area
*/
void *malloc(size_t size);
void* realloc (void* ptr, size_t size);
#endif
/**
* Frees a previously allocated block of memory.
* @param mem The block of memory.
*/
void free(void *mem);
#if defined(ENABLE_MALLOC_MONITORING)
void malloc_print_list(int freeList);
#endif
#if defined(__cplusplus)
}
#endif
#if defined(USE_VERBOSE_MALLOC)
#define malloc(size) malloc_d((size), __FILE__, __LINE__)
#endif
#if defined(USE_VERBOSE_FREE)
#define free(ptr) free_d((ptr), __FILE__, __LINE__)
#endif

View file

@ -5,6 +5,8 @@
#include "varargs.h"
#include "config.h"
#include "malloc.h"
#if defined(__cplusplus)
extern "C" {
#endif
@ -13,29 +15,6 @@ char *itoa(int value, char *str, int base);
int atoi(const char *str);
float atof(const char *str);
#if defined(USE_VERBOSE_MALLOC)
void *malloc_d(size_t,const char *,int);
#endif
#if defined(USE_VERBOSE_FREE)
void free_d(void *,const char*, int);
#endif
/**
* Allocates a block of memory
* @param size Minimum size of the memory block
* @return Pointer to the allocated memory area
*/
void *malloc(size_t size);
/**
* Frees a previously allocated block of memory.
* @param mem The block of memory.
*/
void free(void *mem);
void* realloc (void* ptr, size_t size);
void exit(int errorCode);
static inline void *memset(void *ptr, int value, size_t num)
@ -126,13 +105,6 @@ static inline int strcmp(const char *p1, const char *p2)
return 0;
}
static inline void *calloc(size_t size)
{
void *mem = malloc(size);
memset(mem, 0, size);
return mem;
}
static inline char * strdup(const char *str)
{
size_t len = strlen(str) + 1;
@ -141,6 +113,13 @@ static inline char * strdup(const char *str)
return n;
}
static inline void *calloc(size_t size)
{
void *mem = malloc(size);
memset(mem, 0, size);
return mem;
}
int sprintf(char *target, const char *format, ...);
int vsprintf(char *target, const char *format, va_list vl);
@ -149,12 +128,3 @@ int vsprintf(char *target, const char *format, va_list vl);
}
#endif
#if defined(USE_VERBOSE_MALLOC)
#define malloc(size) malloc_d((size), __FILE__, __LINE__)
#endif
#if defined(USE_VERBOSE_FREE)
#define free(ptr) free_d((ptr), __FILE__, __LINE__)
#endif

View file

@ -6,12 +6,16 @@
void *operator new( size_t size )
{
return calloc( size );
void *ptr = malloc( size );
memset(ptr, 0, size);
return ptr;
}
void *operator new[]( size_t size )
{
return calloc( size );
void *ptr = malloc( size );
memset(ptr, 0, size);
return ptr;
}
void operator delete( void *obj )

View file

@ -208,8 +208,14 @@ void init(const MultibootStructure *mbHeader)
vm_start();
irq_disable();
kputs("\x12\x04trainOS stopped.\x12\x07!\n");
#if defined(ENABLE_MALLOC_MONITORING)
malloc_print_list(0);
#endif
while(1);
}

View file

@ -15,6 +15,10 @@ typedef struct List
size_t length;
size_t used;
struct List *next;
#if defined(ENABLE_MALLOC_MONITORING)
const char *allocationFile;
int allocationLine;
#endif
} List;
size_t mallocCount = 0, freeCount = 0;
@ -26,6 +30,45 @@ static char * const malloc_heap_end = (char *)0x10000000;
List *listBegin = nullptr;
#if defined(ENABLE_MALLOC_MONITORING)
void malloc_print_list(int freeList)
{
List *list = listBegin;
serial_printf(SERIAL_COM1, "malloc list: \n");
size_t count = 0;
while(list != nullptr)
{
#if defined(USE_MAGIC_SECURED_MALLOC)
if(list->magic != 0xDEADBEEF) {
die("malloc::print_list.InvalidMagicNumber");
}
#endif
if(freeList || list->used) {
serial_printf(SERIAL_COM1,
"[%x -> %x] (%s:%d) %d %d\n",
list,
list->next,
list->used ? list->allocationFile : "",
list->used ? list->allocationLine : "",
list->used,
list->length);
kprintf("[%x -> %x] (%s:%d) %d %d\n",
list,
list->next,
list->used ? list->allocationFile : "",
list->used ? list->allocationLine : "",
list->used,
list->length);
if(list->used) {
count++;
}
}
list = list->next;
}
kprintf("Unfreed objects: %d\n", count);
serial_printf(SERIAL_COM1, "Unfreed objects: %d\n", count);
}
#else
static void print_list()
{
List *list = listBegin;
@ -41,6 +84,7 @@ static void print_list()
list = list->next;
}
}
#endif
static void defragment()
{
@ -61,7 +105,11 @@ static void defragment()
}
}
#if defined(ENABLE_MALLOC_MONITORING)
void *_malloc(size_t len, const char *file, int line)
#else
void *malloc(size_t len)
#endif
{
// Prevent fragmentation, sacrifice memory
if(len < minimumAllocSize) {
@ -85,7 +133,11 @@ void *malloc(size_t len)
cursor = cursor->next;
}
if(cursor == nullptr) {
#if defined(ENABLE_MALLOC_MONITORING)
malloc_print_list(1);
#else
print_list();
#endif
die_extra("malloc.OutOfMemory", itoa(len, nullptr, 10));
}
@ -93,17 +145,12 @@ void *malloc(size_t len)
die("malloc.FragmentationFailure");
}
if(cursor->length == len)
{
cursor->used = 1;
}
else
if(cursor->length != len)
{
// Store total length
size_t newLength = cursor->length - sizeof(List) - len;
// Allocate the memory
cursor->used = 1;
cursor->length = len;
// Fragment list
@ -118,15 +165,29 @@ void *malloc(size_t len)
cursor->next = newl;
}
cursor->used = 1;
#if defined(ENABLE_MALLOC_MONITORING)
cursor->allocationFile = file;
cursor->allocationLine = line;
#endif
allocatedMemory += len;
mallocCount++;
return (void*)((char*)cursor + sizeof(List));
}
#if defined(ENABLE_MALLOC_MONITORING)
void* _realloc (void* ptr, size_t size, const char *file, int line)
#else
void* realloc (void* ptr, size_t size)
#endif
{
#if defined(ENABLE_MALLOC_MONITORING)
void *n = _malloc(size, file, line);
#else
void *n = malloc(size);
#endif
memcpy(n, ptr, size);
free(ptr);
return n;
@ -139,13 +200,13 @@ void free(void *ptr)
return;
}
if((uintptr_t)ptr < (uintptr_t)malloc_heap_start) {
die_extra("free.InvalidFree", itoa(ptr, nullptr, 16));
die_extra("free.InvalidFree", itoa((int)ptr, nullptr, 16));
}
freeCount++;
List *entry = (List*)((char*)ptr - sizeof(List));
if(entry->used == 0) {
die_extra("free.InvalidBlock", itoa(ptr, nullptr, 16));
die_extra("free.InvalidBlock", itoa((int)ptr, nullptr, 16));
}
#if defined(USE_MAGIC_SECURED_MALLOC)
if(entry->magic != 0xDEADBEEF) {
@ -175,8 +236,12 @@ void *malloc_d(size_t len, const char *file, int line)
serial_write_str(SERIAL_COM1, itoa(line, nullptr, 10));
serial_write_str(SERIAL_COM1, ": ");
#if defined(ENABLE_MALLOC_MONITORING)
void *ptr = _malloc(len, file, line);
#else
void *ptr = malloc(len);
serial_write_str(SERIAL_COM1, itoa(ptr, nullptr, 16));
#endif
serial_write_str(SERIAL_COM1, itoa((int)ptr, nullptr, 16));
serial_write_str(SERIAL_COM1, "\n");
return ptr;
@ -192,7 +257,7 @@ void free_d(void *ptr, const char *file, int line)
serial_write_str(SERIAL_COM1, "Free ");
serial_write_str(SERIAL_COM1, itoa(entry->length, nullptr, 10));
serial_write_str(SERIAL_COM1, " bytes at ");
serial_write_str(SERIAL_COM1, itoa(ptr, nullptr, 16));
serial_write_str(SERIAL_COM1, itoa((int)ptr, nullptr, 16));
serial_write_str(SERIAL_COM1, " in ");
serial_write_str(SERIAL_COM1, file);
serial_write_str(SERIAL_COM1, ":");

View file

@ -42,7 +42,8 @@ HEADERS += \
include/ker/new.hpp \
include/dynamic.h \
include/config.h \
include/serial.h
include/serial.h \
include/malloc.h
DISTFILES += \
asm/intr_common_handler.S \

View file

@ -96,6 +96,8 @@ namespace trainscript
{
LocalContext context(this->module);
ker::Vector<Variable*> temporaries;
for(auto var : this->module->variables)
{
context.add(var.first, var.second);
@ -115,14 +117,22 @@ namespace trainscript
if(this->mArguments[i].second != arguments[i].type) {
die_extra("ScriptMethod::invoke", "Invalid argument type.");
}
context.add(this->mArguments[i].first, new Variable(arguments[i]));
auto *v = new Variable(arguments[i]);
temporaries.append(v);
context.add(this->mArguments[i].first, v);
}
for(auto local : this->mLocals) {
context.add(local.first, new Variable { local.second, 0 });
auto *v = new Variable { local.second, 0 };
temporaries.append(v);
context.add(local.first, v);
}
this->block->execute(context);
for(auto *var : temporaries) {
delete var;
}
return returnVariable;
}