a thoughtful web.
Good ideas and conversation. No ads, no tracking.   Login or Take a Tour!
comment
rob05c  ·  3178 days ago  ·  link  ·    ·  parent  ·  post: What does your desktop look like, Hubski?

I'd have to dig into it to be sure, but I suspect it's a false positive, depending how you define 'false positive'.

So, the loop doesn't normally exit (unless one of those functions is a heinous macro). So, when you hit C-c, something, presumably `lval_eval`, calls `exit(1)`. When it does, the process immediately terminates, and the memory in `main` allocated by `readline`, `lval_read`, and `lenv_new` won't be deallocated before termination.

    memory leaks are among the worst things and it should not be ignored

Unequivocally. But not cleaning up everything on exit isn't really a memory leak. Any time you exit a program by calling `exit`, you're almost certainly going to leave memory unreleased. That's not really an issue. Some people don't like it, but it's not really a problem. The process terminates, the OS recaptures the memory, end of story.

    at the very least, is going to obfuscate debugging later on.

Agreed. Some people think you should always clean everything up. I tend to think it depends on the size of the app. It certainly makes things cleaner for bigger projects, and easier to track down real memory leaks, because Valgrind & Co don't have 'false positives'.

    avoid in-loop declaration of pointers at all cost

I don't think the loop is the issue. With an `exit`, the whole program is killed. The `lenv_del` outside the loop is never called either, and `e` is also leaked.

Thinking about it more, I don't think what you want is technically possible. The `lval_eval` has to take all the input, and you don't know how big the input will be. Static buffers in a loop can work for getting all the input, but some way, somehow, you have to get data of unknown length to `lval_eval`. So, you could make `lval_eval` take a fixed length and save state for a second call. But then `lval_eval` has to keep dynamic memory, because it might not be 2 buffers' worth, it might be 200. The dynamic allocation is out of the loop, but it didn't go away, it just moved somewhere else.

What you really probably want is garbage collection, or C++ RAII. C just doesn't have a way to specify future deallocation.

If it were me, I'd probably make `lval_eval` return an outparam signalling whether to exit, so the main loop would get the signal and `break` after freeing resources. Not a big deal for a small REPL, but certainly for a big project. Everything is relative.

From an FP perspective, the `exit` is a side-effect, and this is one of countless reasons impure functions make everything harder.