#Bunch of memory leaks even though memory is freed after function returns error

1 messages · Page 1 of 1 (latest)

torpid fjord
#

In my parse function, if I return an error, I get a bunch of memory leaks even though I have my free_identifiers function freeing all the identifiers which're allocated from a GPA and then I free the actual array of tokens.
Is this code not being reached when parse returns the error?

#

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.

woeful orchid
#

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.

torpid fjord
#

Yeah

#

Is there a way to catch that?

woeful orchid
#

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);
torpid fjord
#

Is there a way to catch if the function returns an error so that I can leave the deallocation to the main function?

hybrid blade
#

You could use errdefer

woeful orchid
#

Replace try parse(tokens); with

parse(tokens) catch {
  // handle error
}
hybrid blade
#

Also true

hybrid blade
#

errdefer runs the thing only on errors

torpid fjord
#

I get a segfault now rather than the function returning the specified error. thonkzoom

woeful orchid
#

lol damn, could you post the updated code + whatever file you are running it on?

torpid fjord
#

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

woeful orchid
#

oh yah

torpid fjord
#

Is there a way to exit early once those functions are called within the catch?

woeful orchid
#

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

torpid fjord
#

Yeah

woeful orchid
#

how exactly do you want to clean up? only on error or always when the program exits?

torpid fjord
#

Well, I was hoping both since it seems logical, doesn't it?

woeful orchid
#

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)

torpid fjord
#

I removed the catch block and now I still get a segfault lol.

woeful orchid
#

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

torpid fjord
#

That seems very weird. Why was that decision chosen?

hybrid blade
#

defers run from bottom to top

woeful orchid
#

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);