From 47c3d9a5fc4704f51a61859bb01dee867baeddcb Mon Sep 17 00:00:00 2001 From: adam-mcdaniel Date: Wed, 12 Aug 2020 23:43:56 -0400 Subject: [PATCH] Added memory leak error checks at the end of execution --- examples/leak.ok | 6 ++++ src/target/core/core.c | 45 ++++++++++++------------- src/target/core/core.go | 73 ++++++++++++++++++++++------------------- 3 files changed, 69 insertions(+), 55 deletions(-) create mode 100644 examples/leak.ok diff --git a/examples/leak.ok b/examples/leak.ok new file mode 100644 index 0000000..dbbd573 --- /dev/null +++ b/examples/leak.ok @@ -0,0 +1,6 @@ +#[memory(128)] + + +fn main() { + let x = alloc(8) as &char; +} \ No newline at end of file diff --git a/src/target/core/core.c b/src/target/core/core.c index 37ddb5e..10b1140 100644 --- a/src/target/core/core.c +++ b/src/target/core/core.c @@ -17,34 +17,14 @@ typedef struct machine { const int STACK_HEAP_COLLISION = 1; const int NO_FREE_MEMORY = 2; const int STACK_UNDERFLOW = 3; +const int MEMORY_LEAK = 4; -// Fatal error handler. Always exits program. -void panic(int code) { - printf("panic: "); - switch (code) { - case 1: printf("stack and heap collision during push"); break; - case 2: printf("no free memory left"); break; - case 3: printf("stack underflow"); break; - default: printf("unknown error code"); - } - printf("\n"); - exit(code); -} - -/////////////////////////////////////////////////////////////////////// -///////////////////////////// Debug Info ////////////////////////////// -/////////////////////////////////////////////////////////////////////// -// Print out the state of the virtual machine's stack and heap void machine_dump(machine *vm) { int i; printf("stack: [ "); for (i=0; istack_ptr; i++) printf("%g ", vm->memory[i]); - for (i=vm->stack_ptr; icapacity; i++) - printf(" "); printf("]\nheap: [ "); - for (i=0; istack_ptr; i++) - printf(" "); for (i=vm->stack_ptr; icapacity; i++) printf("%g ", vm->memory[i]); printf("]\nalloc: [ "); @@ -58,6 +38,20 @@ void machine_dump(machine *vm) { printf("TOTAL ALLOC'D %d\n", total); } +// Fatal error handler. Always exits program. +void panic(int code) { + printf("panic: "); + switch (code) { + case 1: printf("stack and heap collision during push"); break; + case 2: printf("no free memory left"); break; + case 3: printf("stack underflow"); break; + case 4: printf("leaked heap memory"); break; + default: printf("unknown error code"); + } + printf("\n"); + exit(code); +} + ///////////////////////////////////////////////////////////////////////// ///////////////////// Stack manipulation operations ///////////////////// @@ -120,6 +114,12 @@ machine *machine_new(int global_scope_size, int capacity) { // Free the virtual machine's memory. This is called at the end of the program. void machine_drop(machine *vm) { + for (int i=vm->capacity-1; i>=vm->stack_ptr; i--) { + if (vm->allocated[i]) { + machine_dump(vm); + panic(MEMORY_LEAK); + } + } // machine_dump(vm); free(vm->memory); free(vm->allocated); @@ -142,8 +142,9 @@ void machine_establish_stack_frame(machine *vm, int arg_size, int local_scope_si double *args = malloc(arg_size * sizeof(double)); int i; // Pop the arguments' values off of the stack - for (i=arg_size-1; i>=0; i--) + for (i=arg_size-1; i>=0; i--) { args[i] = machine_pop(vm); + } // Push the current base pointer onto the stack so that // when this function returns, it will be able to resume diff --git a/src/target/core/core.go b/src/target/core/core.go index 13d283c..54f0c92 100644 --- a/src/target/core/core.go +++ b/src/target/core/core.go @@ -11,6 +11,7 @@ var READER = bufio.NewReader(os.Stdin) const STACK_HEAP_COLLISION = 1 const NO_FREE_MEMORY = 2 const STACK_UNDERFLOW = 3 +const MEMORY_LEAK = 4 func panic(code int) { fmt.Print("panic: ") @@ -24,6 +25,9 @@ func panic(code int) { case 3: fmt.Println("stack underflow") break + case 4: + fmt.Println("leaked heap memory") + break default: fmt.Println("unknown error code") } @@ -52,40 +56,43 @@ func machine_new(global_scope_size, capacity int) *machine { return result } +func (vm *machine) dump() { + fmt.Print("stack: [ ") + for i := 0; i < vm.stack_ptr; i += 1 { + fmt.Printf("%g ", vm.memory[i]) + } + fmt.Println("]") + fmt.Print("heap: [ ") + for i := vm.stack_ptr; i < vm.capacity; i += 1 { + fmt.Printf("%g ", vm.memory[i]) + } + fmt.Println("]") + fmt.Print("alloc: [ ") + for i := 0; i < vm.capacity; i += 1 { + if vm.allocated[i] { + fmt.Printf("1 ") + } else { + fmt.Printf("0 ") + } + } + fmt.Println("]") + total := 0 + for i := 0; i < vm.capacity; i += 1 { + if vm.allocated[i] { + total += 1 + } + } + fmt.Printf("STACK SIZE %d\n", vm.stack_ptr) + fmt.Printf("TOTAL ALLOC'D %d\n", total) +} + func (vm *machine) drop() { - // fmt.Print("stack: [ ") - // for i:=0; i= vm.stack_ptr; i -= 1 { + if vm.allocated[i] { + vm.dump() + panic(MEMORY_LEAK) + } + } } func (vm *machine) load_base_ptr() {