Memory Management ios7 [duplicate] - objective-c

This question already has answers here:
When to use -retainCount?
(11 answers)
Closed 9 years ago.
I have following code:
- (IBAction)HeyCount:(UIButton *)sender {
NSString* strr = [[NSString alloc] initWithString:#"hi there"];
self.string = #"789";
ohYeah = #"456";
NSLog(#"Retain Count of ohYeah:[%d] with String:[%ld]",[ohYeah retainCount],(long)[ohYeah integerValue]);
NSLog(#"Retain Count of strr:[%d] with String:[%ld]",[strr retainCount],(long)[strr integerValue]);
}
And the out put of the above code is:
Retain Count of ohYeah:[-1] with String:[456]
Retain Count of strr:[-1] with String:[0]
Declaration of ohYeah is in .h file
NSString * ohYeah;
I'm not using ARC. Can anyone of you explain why retain count of both strings is -1 and accessing an object with retain count -1 should not be crash?

I guess the compiler is clever and creates string literals from your given code. Since those reside in their own memory space and are never released they get a retain count of UINT_MAX. UINT_MAX printed with %d will result in -1. Use %u for unsigned integers.

You shouldn't look to closely at retainCount.
There are objects like constant strings that don't take part in the retain/release mechanism. For example, #"456" is such a constant string. You can release or retain it as much as you like, nothing will happen.
There are other objects like #123 that are not even objects in a 64 bit system. They behave like objects, but no memory is ever allocated for them.
In both cases, the retain count won't give any sensible result. Which is why it is very, very rare that you should ever look at the retain count.
And then there are methods like "copy" which sometimes copy an object, sometimes just retain the original object. So if you have an object with a retain count of 100, and you make a copy, that copy might have a retain count of 1 or 101.

Note that retainCount is declared like this in NSObject.h:
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
You should use %u to display it on 32 bits architecture and %lu on 64 bits.
But you shouldn't use directly retainCount, use it in your code means that you've a problem of architecture, objective-c (ARC or Manual Reference Counting) give a complete set of mechanism to manage memory and objects life cycle properly.

Related

Printing element removed from nsarray

I am playing with objective-c and did sample test.
In non-arc environment I have the following code:
NSNumber * one;
NSLog(#"At first one retain count is: %d",[one retainCount]);
one = [[NSNumber alloc]initWithInt:5];
NSNumber * two = [[NSNumber alloc]initWithInt:1];
NSNumber * three =[[NSNumber alloc]initWithInt:2];
NSLog(#"After initializing %d",[one retainCount]);
NSMutableArray * array = [NSMutableArray arrayWithObjects:one,two,three, nil];
NSLog(#"After adding to array it is: %d",[one retainCount]);
NSString * a = [array objectAtIndex:0];
NSLog(#"Assigning to variable a: %d",[one retainCount]);
NSLog(#" %# ",a);
[one release];
[array removeObjectAtIndex:0];
NSLog(#"after releasing and removing from array %d",[one retainCount]);
NSLog(#" %# ",a);
It seems like the I wouldn't be able to use nslog the variable a but I can do it.
I am getting the following output;
2013-03-07 17:57:09.706 Interview[33491:11303] At first one retain count is: 3
2013-03-07 17:57:09.707 Interview[33491:11303] After initializing 2
2013-03-07 17:57:09.707 Interview[33491:11303] After adding to array it is: 3
2013-03-07 17:57:09.707 Interview[33491:11303] Assigning to variable a: 3
2013-03-07 17:57:09.707 Interview[33491:11303] 5
2013-03-07 17:57:09.707 Interview[33491:11303] after releasing and removing from array 1
2013-03-07 17:57:09.708 Interview[33491:11303] 5
How it's possible that I can still use the variable a even if I it supposed be deallacated?
You'll get told many times you should not use retainCount, but your question is:
How it's possible that I can still use the variable a even if I it supposed be deallacated?
When an object is deallocated that simply means that the memory that was used for it is added to the pool of available memory. The memory previously in use is not completely overwritten to remove all traces of what was stored in it.
Furthermore when you invoke [one release] this only indicates you no longer have an interest in the object referenced by the value stored in one (and as a result that object's memory may be returned to the free pool) it does not alter the value stored in one itself. So after the call one still contains the reference to where the object was, or still is...
If you wish to make sure you don't use an out-of-date reference you can use code like:
[one release]; one = nil;
Finally you report that before you even allocate your object your first NSLog outputs:
2013-03-07 17:57:09.706 Interview[33491:11303] At first one retain count is: 3
How can you have a retain count of 3 when you've never even allocated an object? The answer is you are lucky your code didn't blow up; when a local variable, which your one appears to be, is created it starts with garbage contents - calling a method using that garbage as an object reference is unwise. Remember Objective-C is not a "safe" language and will not protect you from such errors. Note that instance and global variables are initialised to 0/nil, and invoking methods on nil is supported in Objective-C - you just get 0 back.
Because you can never be fully sure that your object hasn't been retained elsewhere in the framework. Be sure you obey the memory management policy, and let the framework worry about its obligations.
Additionally, don't use retainCount. Apple tells you explicitly not to use it, and it isn't guaranteed to tell the truth.
Directly from the documentation: Do not use this method.
Special Considerations
This method is of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.
To understand the fundamental rules of memory management that you must abide by, read “Memory Management Policy”. To diagnose memory management problems, use a suitable tool:
The Clang Static analyzer can typically find memory management problems even before you run your program.
The Object Alloc instrument in the Instruments application (see Instruments User Guide) can track object allocation and destruction.
Look here, this explains everything more clearly:
http://www.whentouseretaincount.com

Initializing NSMutableArray with and without capacity [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
NSMutableArray initWithCapacity nuances
Objective-c NSArray init versus initWithCapacity:0
What is the difference between following line of code? what is the exact advantage and disadvantage? suppose next I will do 3 addObject operation.
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity: 5];
NSMutableArray *array = [[NSMutableArray alloc] init];
Functionally both statements are identical.
In the first case, you are giving the run time a hint that you will soon be adding five objects to the array so it can, if it likes, preallocate some space for them. That means that the first five addObject: invocations may be marginally faster using the first statement.
However, there's no guarantee that the run time does anything but ignore the hint. I never use initWithCapacity: myself. If I ever get to a situation where addObject: is a significant performance bottleneck, I might try it to see if things improve.
Regularly the difference with object oriented languages and arrays of varying sizes is: the overhead you will get and the page faults at the memory level.
To put this in another way imagine you have an object that requests 5 spaces in memory (just like your first example) and the second object doesn't reserve any space. Therefore when an object needs to be added to the first, there will already be space in memory for it to just fall in, on the other hand the non-allocated-object will first have to request for space on memory then add it to the array. This doesn't sound so bad at this level but when your arrays increase in size this becomes more important.
From Apple's documentation:
arrayWithCapacity:
Creates and returns an NSMutableArray object with
enough allocated memory to initially hold a given number of objects.
...
The initial capacity of the new array. Return Value A new NSMutableArray object with
enough allocated memory to hold numItems objects.

How Objective-C handles the memory of immutable strings [duplicate]

This question already has answers here:
Do I need to release a constant NSString?
(2 answers)
Closed 10 years ago.
In my research I've come across something peculiar.
#interface Class {
NSString *_string
}
- (void) Method1 {
_string = #"ASDF";
}
Intially I thought that _string was part of the autorelease pools and really didn't think about the memory aspect of it.
After reading this SO post Objective C NSString* property retain count oddity
I've realized that no, this is not the case, and that the retain count of _string is actually UINT_MAX
Obviously my thinking that _string was part of the autorelease pool was a fluke, and how I handled the variable just somehow worked out. What I would like to know, though, is: when does #"ASDF" get thrown away? I know I should be using properties and setters, but there is probably a lot of code out there that looks like this since assigning a constant to a variable is so intuitive.
What is the lifecycle of these immutable, literal NSStrings, and when will [_string length] actually return an error since #"ASDF" doesn't reside in memory anymore?
From Is a literal NSString autoreleased or does it need to be released?
Compiler allocated strings (of the format #"STRING") are constant, and
so -retain, -release, and -autorelease messages to them are ignored.
You don't have to release or autorelease foo in this case (but it
won't hurt).
Under the hood when you do
NSString* yourString = #"ABC";
the string will be stored in a area of memory called data segment. This area never changes after the application is launched. Here strings are treated as constants for your app. At the same time a string is an object, so if you want to keep it you call retain or copy.
On the contary when you do
NSString* yourString = // alloc-init
you create an object on the heap. If you forget to release you have a memory leak. If someone else destroy it, and you try to access it, you have a bad access to that memory location.
Hope that helps.
An immutable string (NSString) that is created manually follows the normal reference counting rules and thus life cycle.
In your example, the string is even more special because it is actually a string literal. As is the case for any literal, they reside in special memory and only get destroyed when the executable terminates.

Retain count in objective C return -1

I'm new to objective C, I have a NSMutableArray with 3 objects in it, then I try to print the retainCount of the array. Why the final retainCount return -1? Thanks
NSLog(#"myArray has retain count of %d", [myArray retainCount]);
[myArray release];
NSLog(#"myArray has retain count of %d", [myArray retainCount]);
Result from console:
2010-10-17 11:58:06.407 TestRetainCount [527:a0f] myArray has retain count of 1
2010-10-17 11:58:06.407 TestRetainCount [527:a0f] myArray has retain count of -1
After an object has been deallocated (which may happen after a release), you can no longer rely on its data being intact. You're trying to trust the retain count after it has become invalid.
On a general note, don't use the retain count. Ever. Use the rules in the memory management programming guide, and you'll always get the reference counting correct.
Graham Lee answered the question specific to your example.
not specific to your example, but to your question (subject):
UINT_MAX is often used to denote an object which uses no reference counting (e.g., is never deallocated, such as a singleton), or a custom reference counting implementation.
Can't rely on an accurate retainCount because of the timing autoreleased objects. That said, count your alloc/init, new, retains, etc... and match with corresponding release.

copy an NSMutableString instance returns retainCount of -1

Can someone explain why the last line prints out -1? It happens when copy is called on a NSMutableString, I expect the returnCount of strFour to be 1, since an immutable copy should be returned.
NSMutableString *str =[NSMutableString stringWithString:#"hi"];
NSLog(#"new instantiated variable has a retain cout:");
NSLog(#"%d",[str retainCount]); //1, str is a pointer, its value is a memory address
NSMutableString *strFour =[str copy]; //receiver str is mutable, copy returns an immutable
NSLog(#"%d",[strFour retainCount]); ////strFour s retain count should be 1, but it had a retain count of -1
Thanks a lot.
Never bother looking at the retain count of an object. It is always meaningless to do so. The retain count is likely affected by optimisations “under the hood”. These optimisations rely on the fact that your code follows the Cocoa Memory Management Guidelines. Just worry about sticking to those guidelines and don't bother looking directly at the retain count.
One reason why it could be (-1) because the string “hi” may be cached somewhere and your copy is referring to the cached string. Keep in mind that the retain count is actually an unsigned integer. The documentation dor -retainCount says that for objects that never get released, the retain count should be UINT_MAX (which when printed as a signed decimal will come out as “-1”).