On Nov 17, 2008, at 1:03 AM, Stephen J. Butler wrote:
On Sun, Nov 16, 2008 at 11:52 PM, Sandro Noel <[EMAIL PROTECTED]> wrote:
as it turns out. with the bug fixed the mounts array is left null because
the file does not exist yet.
so further in the program is i try to add to the array, nothing happens.

and if i try "mounts = [[NSMutableArray alloc] init];" only the two arrays
get the same pointer.

Well, then what's happening is obvious. initWithContentsOfFile: fails
because the file doesn't exist, so it performs cleanup (aka, call
release) and returns null. Your next alloc then just happens to grab
the same memory block.

1) never call the init* methods twice on the same object.
2) always use the value returned from an init* method.

To elaborate, the reasons for these are based in the way init methods work:

A) When init methods fail, by convention they release their memory and return nil so the caller knows they failed. B) When init methods succeed, they may return a different object than the original receiver.

To spell this out:

        mounts = [[NSMutableArray alloc] init];

This allocates and initializes an empty NSMutableArray.  Fine.

        [mounts initWithContentsOfFile:someFile]];

There are two possible cases here.

A) If initWithContentsOfFile: fails, it releases the NSMutableArray, which in this case causes the memory to be deallocated, and returns nil. However, you're ignoring the return value, so mounts is now pointing to a deallocated block of memory.

B) If initWithContentsOfFile: succeeds, your program *might* proceed just as you expect. However, it is *very* possible that it returns an object with a different address than mounts had before the call. So mounts *may* still point to a perfectly valid NSMutableArray, but not the one that contains your file contents. It's also conceivable that the original object gets corrupted by the double init (well, we could look at the source for NSMutableArray, but in the general case, there's no requirement that double inits always be safe).

        bonjourServices = [[NSMutableArray alloc]init];

What happened to you is that the memory formerly used by mounts happened to be reused to create bonjourServices. So now you had two variables that point to the same perfectly good NSMutableArray. Note that if bonjourServices was some other kind of object -- for example, a dictionary or a string -- you would have gotten a crash at some point when you tried to send a message to either mounts or bonjourServices that it didn't understand.

The best way to follow Stephen's rules 1 and 2 is to always, *always* combine the alloc and init. Even though the following would have worked (assuming you added the check for a nil return)...

        mounts = [NSMutableArray alloc];
        mounts = [mounts initWithContentsOfFile:someFile]];

...it's just too easy to forget the assignment in the second line. Also, it would be easy to double-initialize by mistake. And finally, it would be jarring to any other Cocoa programmer reading your code, since the combined alloc/init is the established idiom.

--Andy

_______________________________________________

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 [EMAIL PROTECTED]

Reply via email to