[Openmcl-devel] Memory managemet Objective C and Clozure

Willem Rein Oudshoorn woudshoo at xs4all.nl
Sun Sep 19 01:48:32 PDT 2010


Thank you for taking your time to answer, but
I get the feeling we are not understanding each other clearly.
So let me give some background on my experience,

1 - I have programmed extensively in Objective-C and the Foundation
    Framework on OpenStep (not the AppKit framework however).  For this
    I have done overwriting dealloc, writing new proxy classes, changing
    classtypes on the fly for debugging purposes and hacked up the
    GNUstep runtime to debug memory management.

    So I think I got a decent grasp at the Apple Foundation
    #release/#retain/#autorelease mechanism.  
    [This is not to say that I am expert or do not mess up
    occassionally, but more to point out where I am coming from.]

2 - I am relatively new to lisp, and completely new to the 
    Clozure Objective-C bridge
3 - My main problem is trying to get my head around mixing
    garbage collection with the Objective-C memory management.

4 - My previous e-mail was more to explain what I found confusing,
    I did understand that some examples could never work.
    The idea was more to show how subtle of a difference there
    was between working and non-working code, and that it
    depends if you have lisp slots or not.  

Strange behaviour in memory magement
I am still convinced the following is not right:

1 - If you create an instance of an subclass of ns:ns-object
    with lisp slots
2 - You should never use (ccl:terminate-when-unreachable)
    on that instance because:
3 - the *objc-object-slot-vectors* keeps a reference to the instance
4 - This reference only goes away when the #/dealloc is called
5 - So terminate will only be called AFTER dealloc.
6 - Terminate calls #/release [which is wrong!] 
   (This could potentially
    be solved by canceling the 'terminate' call in the dealloc call.
    However I assume that this prevents user code for using the
    terminate.  Which could be considered bad as well.)

I naively made the remark that I thought *objc-object-slot-vectors*
should have weak keys, but as you pointed out that does not work.

Gary Byers <gb at clozure.com> writes:

[About the *objc-object-slot-vectors* hash-table]
> A weak hash table could tell us when an encapsulating lisp object
> becomes garbage, but that isn't what we want to know in this and
> similar cases: the slot-vector should exist as long as the ObjC
> object exists.  (If all encapsulating lisp pointers to the ObjC
> object became garbage, we can't safely remove the slot-vector because
> some  might create a new encapsulating pointer to the object or receive
> such a pointer as an argument)

What would I expect

I have thought a little about it, but what I would expect is that:

1 - As soon as a lisp reference to an objective-C object 'o' is created
    'o' is send a #/retain message.   [*]

2 - As soon as the garbage collector discovers that reference 
    is not longer accessible from the lisp side, 
    it sends a #/release message

3 - If the #/dealloc is called, everything is cleaned up.

However I can see that step 2 conflicts with the
*objc-object-slot-vectors* hashtable.  Because the garbage collector
will always see a reference to the object from the hashtable.

[*] For me this means that (setf *i* (make-instance 'ns:ns-object)) would have
    retainCount 2, 1 for the alloc/init, and 1 for the lisp side
    reference to it.   This would be at least consistent
    with the objective C behavior that i = [[NSObject alloc] init] leaks
    as long as you do not send a release message. 
    But you could also easily argue that it should be 1, to be more like
    lisp objects.

I hope this made things clearer.   

Wim Oudshoorn

More information about the Openmcl-devel mailing list