From ab0c5259e5a3238e176e4b1aed942f5384a2d0c6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 18 Sep 2019 13:33:05 +0200 Subject: Fix leak on parse failure --- include/parser.h | 3 +-- src/compiler.c | 24 ++++++++++++++++-------- src/std/arena_allocator.c | 3 +-- tests/glfw.amal | 2 ++ tests/main.c | 2 -- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/parser.h b/include/parser.h index ae5cfa6..88bed93 100644 --- a/include/parser.h +++ b/include/parser.h @@ -27,8 +27,7 @@ struct Parser { LhsExpr file_decl; Scope *current_scope; bool has_func_parent; - /* Borrowed from @compiler for faster access to allocator. The allocator is thread-specific */ - ArenaAllocator *allocator; + ArenaAllocator *allocator; /* Owned */ amal_compiler *compiler; Ssa *ssa; bool started; diff --git a/src/compiler.c b/src/compiler.c index c10ccc9..7fd4426 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -180,22 +180,23 @@ typedef struct { static CHECK_RESULT int amal_compiler_load_in_this_thread(amal_compiler *compiler, FileScopeReference *file_scope) { Parser *parser; - int result; BufferView filepath; ArenaAllocator *parser_allocator; + int result; + + parser = NULL; + parser_allocator = NULL; result = AMAL_COMPILER_ERR; - cleanup_if_error(amal_mutex_lock(&compiler->mutex, "amal_compiler_load_in_this_thread, create arena allocator")); - cleanup_if_error(arena_allocator_alloc(&compiler->allocator, sizeof(ArenaAllocator), (void**)&parser_allocator)); - amal_mutex_tryunlock(&compiler->mutex); - return_if_error(arena_allocator_init(parser_allocator)); + return_if_error(arena_allocator_alloc(&compiler->allocator, sizeof(ArenaAllocator), (void**)&parser_allocator)); + cleanup_if_error(arena_allocator_init(parser_allocator)); filepath = create_buffer_view(file_scope->canonical_path.data, file_scope->canonical_path.size); amal_log_info("Started parsing %.*s", filepath.size, filepath.data); - return_if_error(arena_allocator_alloc(parser_allocator, sizeof(Parser), (void**)&parser)); - return_if_error(parser_init(parser, compiler, parser_allocator)); + cleanup_if_error(arena_allocator_alloc(parser_allocator, sizeof(Parser), (void**)&parser)); + cleanup_if_error(parser_init(parser, compiler, parser_allocator)); file_scope->parser = parser; - return_if_error(parser_parse_file(parser, filepath)); + cleanup_if_error(parser_parse_file(parser, filepath)); cleanup_if_error(amal_mutex_lock(&compiler->mutex, "amal_compiler_load_in_this_thread, add parser")); parser->index = buffer_get_size(&compiler->parsers, Parser*); cleanup_if_error(buffer_append(&compiler->parsers, &parser, sizeof(parser))); @@ -204,6 +205,13 @@ static CHECK_RESULT int amal_compiler_load_in_this_thread(amal_compiler *compile cleanup: amal_mutex_tryunlock(&compiler->mutex); + /* + This also free's the parser, since it's allocated inside the allocator. + The allocator itself is allocated inside the compiler allocator so that will be free'd + when the compiler allocator is free'd + */ + if(result != AMAL_COMPILER_OK) + arena_allocator_deinit(parser_allocator); return result; } diff --git a/src/std/arena_allocator.c b/src/std/arena_allocator.c index 8b0083d..5e49035 100644 --- a/src/std/arena_allocator.c +++ b/src/std/arena_allocator.c @@ -102,8 +102,7 @@ int arena_allocator_alloc(ArenaAllocator *self, usize size, void **mem) { } int arena_allocator_add_mem(ArenaAllocator *self, usize *result_index) { - void *null_data; - null_data = NULL; + void *null_data = NULL; *result_index = self->mems.size; return buffer_append(&self->mems, &null_data, sizeof(void*)); } diff --git a/tests/glfw.amal b/tests/glfw.amal index d0f02d4..e3c2fc6 100644 --- a/tests/glfw.amal +++ b/tests/glfw.amal @@ -1,3 +1,5 @@ +#!/usr/bin/env amalgam + extern const glfwInit: fn() i32; extern const glfwTerminate: fn() i32; // should return void.... extern const glfwCreateWindow: fn(x: i32, y: i32, title: str, monitor: usize, share: usize) usize; diff --git a/tests/main.c b/tests/main.c index 265a0ea..019f8d9 100644 --- a/tests/main.c +++ b/tests/main.c @@ -190,8 +190,6 @@ static void test_load_gl(void) { FAIL_TEST_CLEANUP(full_path); } - printf("glfw init ptr: %p, glfw terminate: %p\n", glfwInit, glfwTerminate); - if(amal_program_register_extern_func(&program, create_buffer_view_auto("glfwInit"), glfwInit, 0) != 0) { fprintf(stderr, "Unexpected error (alloc failure)\n"); FAIL_TEST_CLEANUP(full_path); -- cgit v1.2.3