#Bunch of memory leaks even though memory is freed after function returns error
1 messages · Page 1 of 1 (latest)
So yeah if I deallocate everything in the parse function, then no memory leaks occur.
It just seems strange that if the parse function errors, then the code written after it is not executed.
If your parse function returns an error, it is also returned from the main function due to using try, so the free_identifiers function called afterwards isn't being run.
If you use defer free_identifiers(tokens) before you call parse it will run on error
and on non-error
I would change your last five lines from
var tokens: []Token = try tokenize(allocator, buffer);
print_tokens(tokens);
try parse(tokens);
free_identifiers(allocator, tokens);
defer allocator.free(tokens);
to
const tokens: []Token = try tokenize(allocator, buffer);
defer allocator.free(tokens);
defer free_identifiers(allocator, tokens);
print_tokens(tokens);
try parse(tokens);
Is there a way to catch if the function returns an error so that I can leave the deallocation to the main function?
You could use errdefer
Replace try parse(tokens); with
parse(tokens) catch {
// handle error
}
Also true
Although this one isn't really what you're looking for I think
errdefer runs the thing only on errors
I get a segfault now rather than the function returning the specified error. 
lol damn, could you post the updated code + whatever file you are running it on?
Here's the updated code and the file it is parsing:
var x = 5
var 10
print(x)
Oh so the free_identifiers and allocator.free defers are what were causing it
Strange
oh yah
Is there a way to exit early once those functions are called within the catch?
you can just return, since you are in main, but that won't fix the problem
what's happening is the defer free... are being run after that catch block anyway, so you end up double freeing
Yeah
how exactly do you want to clean up? only on error or always when the program exits?
Well, I was hoping both since it seems logical, doesn't it?
yeah, then you don't need the catch block, just the two lines with defer will do it
you can remove the catch block and use try again
the defers will get run when main exits, no matter if its normally or by error (from try)
I removed the catch block and now I still get a segfault lol.
Swap around the two defer lines
defers are run in reverse order, so when the defers run it frees tokens first, and then tries to call free_identifiers on the now freed tokens variable
That seems very weird. Why was that decision chosen?
defers run from bottom to top
Because it mirrors usage, generally resources are released in reverse order of how they were created. It lets you group defer free... with its associated creation, e.g.
// Pseudocode
// Defers run bottom to top (status quo)
const slice = try allocSlice(...);
defer free(slice);
try populateSlice(slice);
defer freeElements(slice);