Question

i have some questions about objective-c's memory management,

let's say:

NSString * test= [[NSString alloc] init ]
test=@"msg";
[object setStr1: test ]; // declared as: @property(copy, readwrite)
[object setStr2: test ]; // declared as: @property(retain, readwrite)
[object setStr3: test ]; // declared as: @property(assign, readwrite)

test=@"some other string"

I think str1 will have a copy of tests content: str1 will point to one adress of the memory (heap) that contais msg, this address is not the same pointed by test. right?

about str2:
1. what does it store?, i guess the same address that points test, but it will increase the reference counter of test to 2.
2. when i change the test's content, what does str2 have? I guess it still points to msg

about str3: it's incorrect, right?, what does assign do?

thanks.

bonus question:

NSString * test= [[NSString alloc] init ]
test=@"msg";
test=@"something";

should i release test before changing its content?

Was it helpful?

Solution

The most important thing to take away here: The assignment operator = never mutates (i.e. changes) an object. Mutating an object can only be accomplished by sending it messages (e.g., sending appendString: to an NSMutableString). The assignment operator simply causes a pointer to point to a different object than it did before.

Thus, it is incorrect to say:

(1) NSString * test = [[NSString alloc] init];
(2) test = @"msg";

Line (1) creates an NSString object, and assigns test to point to it. Line (2) does the same thing: it creates a new, unrelated NSString object, and assigns test to point to it. Now the original NSString created by line (1) has nothing pointing to it, and is leaked.

Also, you never need to alloc a string literal; the compiler does this implicitely when you use the @"..." syntax. In general, you will very rarely have to use [NSString alloc] at all (only when you want to use the various init* methods, such as initWithFormat:, etc.)

  1. str1 will point to a distinct copy of the test string. (Errata: According to Eiko, the receiver will simply treat this as a 'retain' if it is immutable. This makes no practical difference if you are behaving correctly.)
  2. str2 will point to the same location as test, and the retain count of the object there will be incremented.
  3. str3 will point to the same location as test, but the retain count will not be incremented.

Generally speaking, strings are immutable, so you cannot change their content. You may have to watch out for instances of NSMutableString, however, which is a subclass of NSString. This is why many people recommend copying strings instead of retaining them, so that, should the string be mutated by another part of the program, your object's copy will be unaffected.

OTHER TIPS

With your second line you already leak memory, because you reassign test to a new object and lose the reference to the object you created in your first line.

Your conclusion to str1 is wrong, because the copy might just return self for immutable types (they don't change anyway, so often the system is smart enough to keep them around just once).

str2 will indeed point to the same object and just increment the retain count. You cannot change test's content, as it is immutable. If it was an NSMutableString, then yes, str2 would show this change, too.

assign for str3 will just "copy the address", so it points to the same object (as str2), but it does not retain it, so it doesn't claim any ownership/interest in that object. If you release it elsewhere, str3 will point to dead memory.

Bonus: As in my introduction, yes, you leak. Assigning @"msg" makes you leak the original object, as @"msg" will create a new one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top