[Openmcl-devel] Cocoa and memory management

Paul Krueger plkrueger at comcast.net
Fri Jul 5 15:35:15 PDT 2013


Autorelease pools are only applicable to data objects that are #/autoreleased and have no effect on objects for which that is never called. It's certainly possible that something within the ns-image init is allocating something that IT autoreleases. Can I infer from your comments that you're doing this in some secondary process (i.e. not on the main event thread)? If so, and if you were doing that without explicitly establishing an autorelease pool, then anything autoreleased as a result of what you were doing (even indirectly within the ns-image init for example) would have resulted in a memory leak. I believe that you should have seen a log message telling you not to do that if that was what was going on; you might check the console log for that. Once you added the OBJC:WITH-AUTORELEASE-POOL call you fixed that problem.

You'll still want to #/release the objects that you create when you are done with them to avoid leaking whatever memory they may allocate. It's even possible that calling #/release on the ns-image resulted in an #/autorelease call on some secondary object. That seems a bit unlikely to me since autorelease is typically something that is done by class convenience constructors, so it would be done at init time rather than dealloc time, but who knows. The autorelease pool associated with the main thread is drained and re-created between events. If the thread where you're doing this is long-lived you may want to consider doing the same sort of thing periodically (i.e. draining the pool and reestablishing a new one) to avoid the big memory build-up and consequent long time to free up memory once the process terminates.

On Jul 5, 2013, at 11:13 AM, Ron Garret <ron at flownet.com> wrote:

> I don't think that's the problem.  If I take a single ns-data instance and do this:
> 
> (loop (#/release (make-instance ns:ns-image :with-data d)))
> 
> it leaks.  And it appears to leak into the autorelease pool, because if I do this:
> 
> (OBJC:WITH-AUTORELEASE-POOL
>  (loop (#/release (make-instance ns:ns-image :with-data d))))
> 
> then it only leaks until I abort the process.  Also, returning to the toplevel takes a long time.
> 
> rg
> 
> On Jul 5, 2013, at 6:15 AM, Paul Krueger wrote:
> 
>> In spite of everything that Gary said (which I certainly wouldn't dispute), it seems to me like you might be leaking memory by not releasing the ns-data instances. They just copy data from the ivictor so disposing of it should be irrelevant with respect to the ns-image object. When the ns-image is initialized it should retain the ns-data (which should have a ref count of 1 already by virtue of its allocation. So releasing the ns-image should result in releasing the ns-data, but not dealloc'ing it. I can't explain why everything goes back to a small size when you run your experiment.
>> 
>> You should be able to test what is going on fairly easily by creating your own subclass of ns-data for which you define a dealloc method that logs when the dealloc occurs (and calls next method as well of course). 
>> 
>> On Jul 5, 2013, at 12:53 AM, Ron Garret <ron at flownet.com> wrote:
>> 
>>> I'm writing some code that grabs a stream of images from a camera and displays them in a window.  The code looks roughly like this:
>>> 
>>> (loop
>>> (multiple-value-bind (v p) (make-heap-ivector ...)
>>>  (read-image-from-camera-into v)
>>>  (let ((img (make-instance ns:ns-image :with-data
>>>               (make-instance ns:ns-data :with-bytes p :length (length v)))))
>>>    (display-image img)
>>>    (dispose-heap-ivector v)
>>>    (#/release img)
>>>    )))
>>> 
>>> I'm trying to figure out if I have a memory leak because of not #/releasing the ns-data instance that I'm allocating, so I let this run for a while.  According to top, I seem to have a leak because the image size grows.  But when I stop the loop, close the listener it was running in, and call GC, the image size shrinks back down again.
>>> 
>>> It seems like there are two possibilities:
>>> 
>>> 1.  I'm allocating memory in the current listener's autorelease pool, and it's getting reclaimed when I close the listener.  Except I'm not calling #/autorelease anywhere.
>>> 
>>> 2.  TOP is lying, and I'm not really leaking at all, but CCL is playing some games with virtual memory that fools top into thinking the image is growing when it's really not.
>>> 
>>> Any hints from those wise in the ways of objc memory management would be much appreciated.
>>> 
>>> Thanks,
>>> rg
>>> 
>>> _______________________________________________
>>> Openmcl-devel mailing list
>>> Openmcl-devel at clozure.com
>>> http://clozure.com/mailman/listinfo/openmcl-devel
>> 
> 




More information about the Openmcl-devel mailing list