On Jun 29, 2011, at 7:17 PM, Wim Lewis wrote:


On 29 Jun 2011, at 5:43 PM, James Merkel wrote:
In the [Memory Management Programming Guide] it says:

"You should typically not manage scarce resources such as file descriptors, network connections, and buffers or caches in a dealloc method. In particular, you should not design classes so that dealloc will be invoked when you think it will be invoked. Invocation of dealloc might be delayed or sidestepped, either because of a bug or because of application tear-down. Instead, if you have a class whose instances manage scarce resources, you should design your application such that you know when you no longer need the resources and can then tell the instance to “clean up” at that point. You would typically then release the instance, and dealloc would follow, but you will not suffer additional problems if it does not."

In my code I close a file in the dealloc method -- so I guess that's a file descriptor. I opened the file in the init method, so it seemed logical to close it in the dealloc method. Also, not to be facetious, if I have a bug in my code, wouldn't I fix it? Granted, at application tear-down, if the file is still open, it won't be closed because dealloc won't be called. But again that comes under the heading of a bug in the code. So I don't understand this injunction.

I don't think it should be treated as a hard rule, but I think it is good advice most of the time, or at least a good starting position.

One way to look at it is that for most objects you're not supposed to assume very much about their lifetime. You know they exist as long as you have a refcount to them, but they *may* continue to exist after you release them. This is the semantic of -release. You may happen to know, in a particular piece of code, that you have the only reference to something and it will be dealloced with a given release. But thinking of release as equivalent to dealloc will get you into trouble.

Even ignoring GC (which makes dealloc/finalize even more uncertain), you might end up stashing a reference to that object somewhere else, extending its lifetime. Maybe it's in an NSNotification or an undo stack or a debug log, or there's a situation where your autorelease pool lasts longer than you expect (perhaps you are dealing with a bunch of files in a loop as you load or save a document, eg). In my experience it isn't *usually* a problem of leaking the file handles entirely; it's a problem if I temporarily accumulate too many of them, or if I need the file handle (or socket or...) to be closed before I do some operation, and simply calling -release isn't normally a guarantee of that.

My preferred approach is to have a -close or -invalidate method that releases resources, breaks retain cycles, etc.. If -invalidate isn't called before dealloc, that's OK, but I can also call -invalidate explicitly if I know I want to tear down the object at a given time.

I think there are cases where the indefinite lifetime *is* what you want, if you have objects that can lazily fault something in from disk, or which encapsulate a sharable server connection, or etc. But those objects should be the exception, so that you can be especially aware of lifecycle issues in any code that deals with them. And even so, I usually end up having to give them an -invalidate method eventually, to deal with some odd situation.



I guess I do think of the delloc being called as a result of my release -- and that seems to be the way it is working.

The approach I'm using now is to open the file in an init method, then read a few 100 bytes of header in another method, then find pointers to read other portions of the file and read some more data, then close the file in the dealloc method. Lazy loading of data is an Objective - C/Cocoa pattern.

The alternative would be to open the file, read the entire file, and close it in the init method. I guess this is the approach used by NS methods such as: initWithContentsOfFile, etc. However, the file could be megabytes in size, and so this would be considerably slower.

Another alternative would be to not use a class but just use C functions to do this, but that wouldn't be a Cocoa pattern at all.

Bottom line though, what are the consequences of leaving a file open? When does it finally get closed?

Jim Merkel_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to