[Openmcl-devel] Cocoa memory management and containers
ron at flownet.com
Thu Feb 6 02:00:14 UTC 2020
This is not a CCL question, it’s a Cocoa memory management question, but since i’m not plugged in to the Cocoa development community and I actually am developing in CCL I thought I’d ask here.
I want to extract and use bitmap representations of ns-images. I wrote the following code:
(defun image->bitmap (img)
;; Check to see if the image already has a bitmap
with e = (#/objectEnumerator (#/representations img))
as rep = (#/nextObject e)
until (%null-ptr-p rep)
if (typep rep ns:ns-bitmap-image-rep) return rep)
;; Otherwise create one and add it to the image
:mv (w h) (size img)
bitmap (#/alloc ns:ns-bitmap-image-rep) ;; Memory leak
(ns:with-ns-rect (r 0 0 w h)
(#/initWithFocusedViewRect: bitmap r)))
(#/addRepresentation: img bitmap)
The BB macro is a general-purpose binding construct (it stands for binding-block). :MV is multiple-value-bind. Those details don’t really matter. The only thing that matters is the logic flow: I first check to see if the image already has a bitmap and if so I return that, otherwise I create a new one.
The problem is that this leaks memory because (AFAICT) the bitmap that I create is NOT released when the image is released.
AFAICT this is a general problem with ObjC containers. Putting an object inside a container does NOT increment its reference count, and likewise, removing it does not decrement the reference count.
This seems to me to undermine the whole point of reference counts, and makes it nearly impossible to write a non-leaky version of IMAGE->BITMAP. The only way I can think of to do it is to create a superclass of ns-image that somehow does the Right Thing when it is released. But I have a hard time believing that this is really the right answer. Surely Cocoa memory management is not really this brain-dmanaged, and there is something that I have overlooked?
Advice from anyone more wise in the ways of ObjC would be most welcome.
More information about the Openmcl-devel