Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Right-click on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
From: Just van Rossum <just@le...> - 2003-06-30 14:07:10
|
Chris Ryland wrote: > Uh-oh--can you explain to the uninitiates why these two code sequences > aren't identical? (Cleaning up the code sequences a little bit) #1: app.setDelegate_(AppDelegate.alloc().init()) vs. #2: delegate = AppDelegate.alloc().init() app.setDelegate_(delegate) This is pretty messy, but IMO that's not PyObjC's fault. PyObjC makes sure that Python's refcounting is synchronized with ObjC's, meaning that if you do x = SomeObject.alloc().init() there is exactly one reference to the created instance: the variable 'x'. If 'x' goes out of scope, the value it's pointing to goes away. Code snippet #1 creates an object, passes that to setDelegate_(). The app object stores a pointer to the new instances. Normally storing a pointer means the reference count is incremented (the object is "retained" in ObjC terms). In pure Python, it is guaranteed this will happen. Cocoa on the other hand has quite a few places where it uses what I call a poor man's weak reference scheme, meaning it will store a pointer *without* incrementing the reference count. This is to avoid references cycles (in any straight refcounting scheme, cycles cause leaks unless the cycles are explicitly broken). So what happens in snippet #1 is that the app object stores a pointer, but the instance will be freed by Python when setDelegate_() returns; after all, there are no hard references to it anymore! So we have a stale pointer, causing a crash. Snippet #2 works around this by sticking the object in a (local) variable, ensuring the object stays around as long as the variable is in scope. Since the event loop is run in the same function, this is long enough. Using a variable is just one way to work around the problem, the other one is to simply call .retain() on the delegate object, "artificially" increasing the reference count, creating a leak on purpose. That's ok, since the app delegate is supposed to be alive for the lifetime of the app anyway. The real solution however, is to use Interface Builder. It should be quite rare you have to worry about this: most of the time when Cocoa uses these "weak references", it is guaranteed the references object is alive long enough. For example _usually_ you'll instantiate your app delegate in your main nib file and assign it as the delegate of the app there (by means of an outlet connection). A weak reference is still used (as is actually the case with outlets in general!), but you don't have to be aware of it since Cocoa will automatically do the right thing. It's only when you manyally work with delegates (or rather, outlets in general) you sometimes come across this problem. Just |