Fast forward a few decades, and we're still very much on this journey of finding the right abstractions/interfaces/libraries/languages. I feel like there must be a complexity equivalent to Parkinson's law: complexity expands to fill the space left in between abstractions.
Imagine if this was a new language that the dev community was seeing for the first time. It's hard to imagine it gaining much traction.
So while a much older date is probably appropriate, maybe 20-30 years ago, we can at least mark this (2022) until somebody justifies a particular previous date.
Love it!
Garbage collectors don't guarantee the absence of memory leaks. GCs remove one important source of memory leaks but it's still very possible in GC languages to use up all available memory unintentionally simply by holding onto things in a big data structure that you've forgotten about (often it's a cache). Weak pointers in conjunction with GC help a great deal with that problem but even so GC and weakness are not going to guarantee leak-prevention in all cases.
I still strongly prefer GC languages to the alternative.
https://repo.autonoma.ca/repo/mandelbrot/blob/HEAD/main.c
When writing:
fractal.image = image_open( fractal.width, fractal.height );
I will immediately write below it: image_close( fractal.image );
This hides memory allocations altogether. As long as the open/close functions are paired up, it gives me confidence that there are no inadvertent memory leaks. Using small functions eases eyeballing the couplings.For C++, developing a unit test framework based on Catch2 and ASAN that tracks new/delete invocations is rather powerful. You can even set it up to discount false positives from static allocations. When the unit tests exercise the classes, you get memory leak detection for free.
(I don't mind down votes, but at least reply with what you don't like about this approach, and perhaps suggest a newer approach that we can learn from; contribute to the conversation, please.)