Banging the Bottom End
Join Date: Jun 2004
|
Mmmm, can you smell that? It's that new forum smell! *takes deep whiff*
Got an Objective-C question for all of you: In one of the methods in my Musical Scale program, I return the scaleArray like so: return [scaleArray copy]; Now, scaleArray starts life as an NSMutableArray. When I return the copy, it is immutable, i.e. a NSArray. This isn't a problem, but a weird quirk seems to happen. Instead of the objects in the array having retainCounts of 1, they have retainCounts equal to their retainCount from scaleArray +1. In order to release this returned array, I do the following: for(i=0; i < [returnedArray count]; i++) [[returnedArray objectAtIndex:i] release]; Then, once I've done what I need to do with the array I call [returnedArray release]; This properly releases all the objects and removes a pesky memory leak that I spent some time tracking down. My question is, how do I get my initial array copy to not tack on the previous retainCounts from the original array? Or who knows, maybe this is some kind of feature in NSMutableArray? If it is hopefully it doesn't get omitted in a future release of OS X and cause my program to crash. |
quote |
Veteran Member
|
Not really a Cocoa/Obj-C programmer, so I'll post a bunch of links and hopefully one of them will help.
Sounds like there's something with immutable versions of the Foundation classes that may do some optimization during copies, which might be doing something you wouldn't otherwise want: http://developer.apple.com/documenta...0000049-999791 Sounds like some people were running into problems with this, though they didn't try mixing copy from NSMutableArray to NSArray: http://www.idevgames.com/forum/archi...hp/t-9250.html Based on what I read, maybe doing a initWithArray:copyItems and setting the flag to YES would work, not sure though. http://developer.apple.com/documenta...ray:copyItems: |
quote |
Member
Join Date: Nov 2004
Location: Planet Earth
|
The reason this happens; is that your 'copy' of the array; is only returning a new NSArray object (a shallow vs a deep copy). The objects within the NSArray are not copied, only their references.
However, since each reference to an object in the array needs to be retained by the array; the retain count on each object is incremented. You shouldn't have to decrement the counts on the objects when releasing your new array; it should decrement all the retain counts on the objects within that array. Why are you returning a copy of your array anyway; why not just return the array pointer? Yonah was the biblical prophet who got swallowed by a whale. Great name Intel! |
quote |
Banging the Bottom End
Join Date: Jun 2004
|
Quote:
Quote:
Quote:
Basically I want to set up walls between objects so there's no possibility of object B screwing up what are essentially private members of object A. If I return a pointer to the array, then there is the possibility I could modify objects in that array and that wouldn't be good. In a program as simple as my Musical Scales program this shouldn't be a problem, but I want each object to completely exist on its own. This way I can reuse my Note and ScaleGenerator objects in new projects without having to remember "Oh this object returns a pointer instead of a copy so I can't modify the stuff I get from this object." Also, it was the only way I was able to successfully eliminate the Note object memory leaks that were occurring in my program. [edit] MCQ, Thanks for the links. I'll check them out to see if I can come up with a better solution then the one I'm currently using. |
|||
quote |
Selfish Heathen
Join Date: May 2004
Location: Zone of Pain
|
Quote:
</reassuring> |
|
quote |
Member
Join Date: Nov 2004
Location: Planet Earth
|
Ok, from the links provided by MCQ, copy: does return you a deep copy of the array and the objects. It's mutableCopy: that returns a shallow copy.
This is what I think is happening: the array's objects are individually duplicated with copyWithZone: (which means they would initially have a refcount of 1) the new array is initialized with the copy of old objects using the method initWithObjects: (this increments the refcount to 2) This is the documentation for "initWithObjects: - (id)initWithObjectsid)firstObj, ... Initializes a newly allocated array by placing the objects in the argument list in it. This list is a comma-separated list of objects ending with nil. Objects are retained as they’re added to the array. After an immutable array has been initialized in this way, it can’t be modified. Returns an initialized object, which might be different than the original receiver." Yonah was the biblical prophet who got swallowed by a whale. Great name Intel! |
quote |
Posting Rules | Navigation |
|
Thread Tools | |