That is not to say that garbage collection is an unambigous win. There are real downsides to using it. But for most programs, those modern garbage collectors are good enough that those downsides just don't matter.
That is not to say that garbage collection is an unambigous win. There are real downsides to using it. But for most programs, those modern garbage collectors are good enough that those downsides just don't matter.
Sure, you haven't lost the handle to the memory, but you can still "leak" memory with a GC. Happens all the time. Add to data structure at state 1, do something in state 2, remove data in state 3. What happens you never hit state 3?
> But for most programs, those modern garbage collectors are good enough that those downsides just don't matter.
I mostly agree with this. Although, most programs hit a point where you have to be aware what the GC is doing and try to avoid additional allocations. Which isn't very ergonomic at times. And is often more fucking around than manual memory management, just concentrated to a smaller portion of the code base.
Yes it is, by definition a memory leak is any memory that has been reserved but won't be read from or written to. If you allocate memory into a data structure and after some point in time you will never read from or write to that memory, then that memory constitutes a leak.
The upsides of the definition you gave are that it's simple, well defined, and maximally precise (nothing that is safe to collect is considered live)
The significant downside to this definition is that it's uncomputable. To know if memory is used requires knowing if a loop halts.
The second definition of memory leak is "unreachability" which is a bit harder to nail down. It's a conservative approximation of the first definition, but is more popular because it's computable, and it's practical to write programs with or without GC that don't leak
that's an useless definition as otherwise it would be trivial to augment, say, malloc to prevent memory leaks.
I would define a leak as unused memory that it is not otherwise reusable by a program.
What happens if you never escape a while loop? Should we ban while loop then? Bugs happen, we fix them. But I haven't had a memory bug in years outside of C and C++.
f := createFile("/tmp/defer.txt")
defer closeFile(f)
writeFile(f)https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
I just recently updated a few small services to C# 12 and there's a bunch of little niceties like this I'm finding (spread operator for instance).
// Disposed when goes out of scope
using var http = new HttpClient();
var text = await http.GetStringAsync("https://example.org/");Swift as another one, RC is a GC algorithm, before the usual clueless reply from people not educated in CS.
Followed by FP languages now adopting effects and linear type systems, alongside their automatic memory management approaches.
function closure() {
var smallObject = 3;
var largeObject = Array(1000000);
function longLived() { return smallObject; }
function shortLived() { return largeObject; }
shortLived(); return longLived;
}
Will keep largeObject alive.You really do have to know the quirks of what you're targeting.
Well, the reference lua implementation handles this case fine, and it's a solid but not at all smart™ codebase.
You could test this with your code by setting a FinalizationRegistry to log when they're both finalized, unset any outside reference to `longLived`, and then do something to force a GC (like run Node with --expose-gc and call `global.gc()`, or just allocate a big Uint8Array).
> those modern garbage collectors are good enough that those downsides just don't matter.
This is not what I see. Every I look at a profile of a program written in a GCed language, most of the time is spent in the garbage collector. I can't recall the last time I looked at a c++ profile where more than 10% of the time spent in new/delete. I have seen 100x speedups by disabling GC. You can't ship that, but it proves there is massive overhead to garbage collection.
It doesn't have to be that way. The BEAM is designed for tiny processes, and GC is cheap.
Also, when your process has a giant heap, the GC gets expensive. There's been lots of improvement over the years, but I used to have processes that could usually go through N messages/sec, but if they ever got a backlog, the throughput would drop, and that would tend towards more backlog and even less throughput, and pretty soon it will never catch up.
That sometimes happens with other GC systems, but it never feels quite so dire.
Just like not all malloc()/free() were born equal, to the point companies did made big bucks selling specialised implementations.
I could have disabled the GC to get the same speed up.
It's easy to get in trouble with an interconnected object graph: you mess up and hold onto a pointer that you shouldn't be holding onto, which results in a leak.