"What's possible, though, is accumulating Python objects in memory and keeping strong references to them12. For instance, this happens when we build a cache (for example, a dict) that we never clear. The cache will hold references to every single item and the GC will never be able to destroy them, that is, unless the cache goes out of scope."
Back when I worked with a Java memory profiling tool (JProbe!) we called these "lingerers". Not leaks, but the behaviour was similar.
I can't find the documentation now, but had a similar problem with ASP.NET's Master Page. The example of using data binding to dynamically adjust the menus had the binding go to a backing Page instance. That seemed logical. Unfortunately after about 200 visits to the site, the whole thing fell over. Turns out master pages hold a reference to the backing page even once the whole page is rendered. This caused them to stack up in memory. The fix was to use a static method to provided the data. It was in a user note at the bottom of the page.
I don't have that much experience in Java, but you're absolutely right. Those "lingerers" can happen in pretty much any language with a GC, but they're technically not leaks.
The cache will hold references to every single item and the GC will never be able to destroy them, that is, unless the cache goes out of scope
Had the reverse happening a while ago and it's nasty as well: some C++ objects were holding references to a Python objects, but due to the GC not scanning those memory regions (they're not Python-owned after all), the Python objetcs would get GC'd and all hell broke loose when the C++ tried to access the now dead Python objects. Solution is forced 'lingering', i.e. is applying some RAII adding the Python objects to a global dict and removing them when the C++ objects go out of scope.
Python is reference counted. This was happening because you didn't increment the reference count for python objects you were referencing from C++. Your RAII should increment/decrement reference counts on the object, not place objects into a global dict. That's the "correct" way to reference python objects.
Python's GC doesn't scan memory in the same way other languages do. Instead, it detects cycles between python objects. As long as you follow the reference counting rules correctly, you shouldn't have to worry about it. (Unless you need to detect cycles involving your C++ objects.)
You assume CPython, or some other reference counted implementation though. I'm talking about MicroPython which uses mark&sweep. And which I obviously should have mentioned but I guess I was tired and I didn't.
Back when I worked with a Java memory profiling tool (JProbe!) we called these "lingerers". Not leaks, but the behaviour was similar.