is the copy method broken in Tiger?

Member
Posts: 208
Joined: 2005.04
Post: #1
After a bit of experimenting, I've discovered that the copy method (the one from NSCopying protocol) seems to create objects which have, IMHO, an improper retain count.

For example, the following code snippet prints out 2:

Code:
NSArray *a = [[NSArray alloc] init];
NSArray *b = [a copy];
NSLog(@"%d", [b retainCount]);

i.e. b is getting whatever a's retain count is + 1.

I was under the impression that the object which invoked a's copy method to create b is the sole "owner" of b. Thus, I think b should have a retain count of 1.

Has the copy method always worked this way, or is a bug (or "new feature", like NSNumber caching) in Tiger?

Andrew
Quote this message in a reply
Member
Posts: 208
Joined: 2005.04
Post: #2
Apple even states in their documentation that copied objects should start out with a retain count of one.
Quote this message in a reply
Member
Posts: 72
Joined: 2004.06
Post: #3
Hmm, this makes two threads about weird retain counts now...

Did some testing of my own and it seems that 'a' retains 'b' in the copy method and releases it in dealloc:

Code:
NSArray *a = [[NSArray alloc] init];
    NSLog(@"a retain count: %d", [a retainCount]);
    NSArray *b = [a copy];
    NSLog(@"b retain count: %d", [b retainCount]);
    [a release];
    NSLog(@"[a release]");
    NSLog(@"b retain count: %d", [b retainCount]);

Output:

a retain count: 1
b retain count: 2
[a release]
b retain count: 1

Well, at least this means it's not leaking. But it also means Apple is lying in their docs.

Weird!
Quote this message in a reply
Member
Posts: 72
Joined: 2004.06
Post: #4
Oh, hang on. Check the bottom of the page you link to:

Immutable classes can implement NSCopying very efficiently. Since immutable objects don’t change, there is no need to duplicate them. Instead, NSCopying can be implemented to retain the original. For example, copyWithZone: for an immutable string class can be implemented in the following way.

- (id)copyWithZone:(NSZone *)zone {
return [self retain];
}

A further check:

Code:
NSMutableArray *a = [[NSMutableArray alloc] initWithCapacity:10];
    NSLog(@"a retain count: %d", [a retainCount]);
    NSMutableArray *b = [a copy];
    NSLog(@"b retain count: %d", [b retainCount]);
    [a release];
    NSLog(@"[a release]");
    NSLog(@"b retain count: %d", [b retainCount]);

correctly outputs:

a retain count: 1
b retain count: 1
[a release]
b retain count: 1
Quote this message in a reply
Member
Posts: 208
Joined: 2005.04
Post: #5
Thanks Corun! Grin

So copy, when used on an immutable object, does the exact same thing as retain? That seems kinda redundant and semantically incorrect to me, but I guess I'll just have to live with Apple's decision. At least now I know why some of my retain counts seem awry while trying to debug this retain/release problem my app has been having the past few days (it still doesn't fix the bug though Sad).
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #6
It's just an efficiency thing -- when copy is indistinguishable from retain, why not use the cheaper option?
Quote this message in a reply
Member
Posts: 208
Joined: 2005.04
Post: #7
OneSadCookie Wrote:It's just an efficiency thing -- when copy is indistinguishable from retain, why not use the cheaper option?

I definitely agree that retain should be used instead of copy on immutable objects due to efficiency, but I figure it's the programmer's job to due that, and that Apple shouldn't enforce it. The reason being that a copy method which actually copies an object (and sets the new one's retain count to 1) could be very useful when trying to track down a retain/release bug. Sure, there are work-arounds like...
Code:
NSNumber *newNum = [[NSNumber alloc] initWithLong:[oldNum longValue]];
but having a copy method which actually copies things would be a bit less cumbersome. I dunno.. maybe I'm just jaded from frustrations surrounding a retain/release bug I'm been trying to fix the past few days Wink

On that last note, I have yet another question with regards to retaining/releasing... but I guess I should start a new thread for that.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #8
The programmer might not have another NSNumber with the right value lying around. It's an easy way for Apple to speed up all Cocoa apps a little bit.

You're just jaded Rasp
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Is -fconstant-string-class broken under the XCode/Next runtime Justin Brimm 17 7,764 Jun 12, 2008 01:04 PM
Last Post: Justin Brimm
  C++ copy constructor with subclasses IBethune 6 7,001 Jan 27, 2007 04:57 PM
Last Post: akb825
  Copy Protection Barclay 2 2,422 Apr 20, 2006 02:37 PM
Last Post: KittyMac
  Quicktime broken? unknown 4 2,986 Apr 17, 2006 08:10 AM
Last Post: Nick
  Is Force Feedback broken in Tiger? Andrew 3 3,551 Aug 23, 2005 03:59 AM
Last Post: Andrew