Is it safe to count on ints always being initialized to 0 in Objective-C?
More specifically, when an object with int ivars has been newly instantiated, is it safe to assume that its ivars have value 0?
Yes, class instance variables are always initialized to 0 (or nil, NULL, or false, depending on the exact data type). See the Objective-C 2.0 Programming Language:
The alloc method dynamically allocates memory for the new object’s instance variables and initializes them all to 0—all, that is, except the isa variable that connects the new instance to its class.
EDIT 2013-05-08
Apple seems to have removed the above document (now linked to The Wayback Machine). The (currently) active document Programming With Objective-C contains a similar citation:
The alloc method has one other important task, which is to clear out the memory allocated for the object’s properties by setting them to zero. This avoids the usual problem of memory containing garbage from whatever was stored before, but is not enough to initialize an object completely.
However, this is only true for instance variables of a class; it is also true for POD types declared at global scope:
// At global scope
int a_global_var; // guaranteed to be 0
NSString *a_global_string; // guaranteed to be nil
With one exception, it is not true for local variables, or for data allocated with malloc() or realloc(); it is true for calloc(), since calloc() explicitly zeros out the memory it allocates.
The one exception is that when Automatic Reference Counting (ARC) is enabled, stack pointers to Objective-C objects are implicitly initialized to nil; however, it's still good practice to explicitly initialize them to nil. From the Transitioning to to ARC Release Notes:
Stack Variables Are Initialized with nil
Using ARC, strong, weak, and autoreleasing stack variables are now implicitly initialized with nil
In C++ (and C++ objects being used in Objective-C++), class instance variables are also not zero-initialized. You must explicitly initialize them in your constructor(s).
I don't think you should assume any values for initialization. If you are building logic around a "0" value, you should set it to be sure.
Yes, in C global vars are initialized to zero.
In Objective-C even local vars are initialized to zero.
You can count on it.
Related
Let's say I have a method that returns an object pointer
-(MyObj *) returnMyObj {
MyObj *obj = [MyObj alloc] init];
return obj;
}
If I call this function without assigning the pointer like this
Scenario 1
[self returnMyObj];
and if I call this function with assignment to a pointer like this
Scenario 2
MyObj* obj = [self returnMyObj];
Compiler can release the object at the end of the returnMyObj method call in the Scenario 1 but it cant do the same in Scenario 2.How does ARC decide if it needs to retain the created object at the end of method invocation or not in both cases?
Here is what the ARC article in the documentation has to say:
To make sure that instances don’t disappear while they are still needed, ARC tracks how many properties, constants, and variables are currently referring to each class instance. ARC will not deallocate an instance as long as at least one active reference to that instance still exists.
To make this possible, whenever you assign a class instance to a property, constant, or variable, that property, constant, or variable makes a strong reference to the instance. The reference is called a “strong” reference because it keeps a firm hold on that instance, and does not allow it to be deallocated for as long as that strong reference remains.
ARC decides which objects will be kept in memory and which will be deallocated by counting the strong references to the objects.
In your second scenario you are creating a strong reference to the MyObj instance and ARC will not deallocate it while the object is in use. In this case it will be deallocated when the method that uses this object finishes.
The optimizer may absolutely release the object in scenario 2 at the end of the statement if obj is not referenced later in the block.
The whole point is that the optimizer can see when the pointer is referenced, and may release it as soon as the last reference is completed. obj does not have precise lifetime semantics, so it only extends the life of the object until the last time obj is referenced, not when obj goes out of scope.
In scenario 1, the reference is not assigned to any variable, so it clearly has no later references, and may be immediately released. That said, it may not immediately release the object, since returnMyObj does not transfer ownership to the caller (due to its name). So the object may not actually be released until the autorelease pool drains.
Question 1
Supposed I have this code:
MyClass * __strong foo = [MyClass new];
MyClass * __strong bar = foo;
// foo = nil; // by ARC?
In reference to this answer, does ARC automatically nil out foo on line 3 since bar already acquired the reference?
Question 2
//ECGService.m
#property (strong) MuttableArray *rriData;
(MuttableArray *)getRriData {
return _rriData;
}
//AlgorithmTest.m
// according to Apple docs, local variable are marked __strong by default
MuttableArray *rriData = [self.ecgService getRriData];
for(NSNumber *rri in rriData) {
// use rri!
}
// rriData = nil;
Should I nil out the local variable rriData after using it?
And, does the __strong attribute must only be applied to only one instance of an object?
Answer 1.
In principle, ARC doesn't “nil out” foo until it goes out of scope. When it goes out of scope, ARC releases its reference. It doesn't have to actually set foo to nil, but the effect is exactly as if ARC does set it to nil.
In practice, ARC is usually allowed to release the reference held by foo immediately after the last use of the foo variable, which may be long before it goes out of scope. In your example, if the only place where you use foo in the function is in the assignment to bar, then ARC is allowed to release foo's reference immediately after that assignment. Note that generally there's no way for you to know about this early release because you don't use foo again! Note also that bar will still reference the object unless bar is also not used later in the function.
There are some special attributes that can prevent ARC from performing this early release, called objc_precise_lifetime and objc_returns_inner_pointer but usually applied through the macros NS_VALID_UNTIL_END_OF_SCOPE and NS_RETURNS_INNER_POINTER. These are advanced features that you probably won't have to worry about any time soon, but if you want to see some examples of NS_RETURNS_INNER_POINTER, take a look at NSString.h.
Answer 2.
You don't need to “nil out” rriData. ARC will release its reference when it goes out of scope (or sooner—see answer 1).
You don't need to say __strong usually, because it's the default, and it's what you want usually. It is normal to have multiple strong references to an object. You use __weak explicitly when you need to prevent a retain cycle. There are many explanations of retain cycles on the web and on stack overflow, so if you need to learn about them, please visit your favorite search engine.
In reference to this answer, does ARC automatically nil out foo on line 3 since bar already acquired the reference?
No. ARC stands for Automatic Reference Counting. Obviously counting does not stop with 1.
It is the strength of ARC that every reference is handled independently of other references. A strong foo retains the referred object as long as it points to. It does not matter, whether other reference variables points to the same object. Track every reference isolated.
There is only one case that let ARC change the value of a reference variable: If it is marked with weak and there is no other strong reference to the object. This is the intended behavior.
As a result of optimization it is possible that retains and releases are omitted or different local variables in source code are put together. This is transparent for you.
Should I nil out the local variable rriData after using it?
You should not care about this. A strong reference variable automatically retains an object, whose reference is stored in the reference variable. And it automatically releases the object, if it does not point any longer to it. This includes releases on
a new value is assigned to the reference variable
nil is assigned to the reference variable
the reference variable loses it extent (lifetime).
Because of the last fact, there will be an automatically generated release, when rriData loses it extent. There is no reason to nil it out in advance.
Question 1. No, you simply end up with two references to the MyClass instance. Nothing gets nilled out.
Question 2. No, you don't need to nil out anything. ARC manages memory for you. That's the point. You also never need to say __strong. It is the default.
When declaring the properties in Objective-C, what are the custom options available to configure, which define how the accessor methods would behave?
For example, you can have weak, strong, readonly.
Here's the short answer:
atomic vs nonatomic primarily ensures that complete values are returned from synthesized getters and that complete values are written by synthesized setters.
readwrite vs readonly determines whether a synthesized property has a synthesized accessor or not (readwrite has a setter and is the default, readonly does not).
assign vs weak vs retain vs copy determines how the synthesized accessors interact with the Objective-C memory management scheme.
And now for the long answer:
Atomic v Nonatomic
Assuming that you are #synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory.
With atomic, the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than atomic.
What atomic does not do is make any guarantees about thread safety. If thread A is calling the getter simultaneously with thread B and C calling the setter with different values, thread A may get any one of the three values returned -- the one prior to any setters being called or either of the values passed into the setters in B and C. Likewise, the object may end up with the value from B or C, no way to tell.
Ensuring data integrity -- one of the primary challenges of multi-threaded programming -- is achieved by other means.
Assign, weak, retain, copy
In a nutshell, assign vs weak vs retain vs copy determines how the synthesized accessors interact with the Objective-C memory management scheme:
assign is the default and simply performs a variable assignment. It does not assert ownership, so the object pointed to by the property's pointer may disappear at any time if no others have asserted ownership themselves through retain or other means. In an ARC environment, assign does not ensure that pointers will not dangle, which means a pointer may end up pointing to junk if the object on the other side has been deallocated.
weak is identical to assign, except that it will zero out pointers that lead to deallocated objects to stop them from dangling. Weak is only available in an ARC environment.
retain specifies the new value should be sent -retain on assignment and the old value sent release. Retain is also know as strong.
copy specifies the new value should be sent -copy on assignment and the old value sent release. Copy is often used for properties in which the type of the property has a mutable cousin (NSArray/NSMutableArray) to prevent others from sending in mutable versions and altering them/having them altered behind their backs, and more.
Remember that retain/strong is done on the created object (it increases the reference count) whereas copy creates a new object. The difference, then, is whether you want to add another retain to the object or create an entirely new object.
I have member variables in my custom UIViewController that are defined as 'assign' (not 'retain') like this:
#property (nonatomic, assign) UIButton* mSkipButton;
In my loadView method, I set the var, for instance self.mSkipButton, to an autoreleased alloc of the variable type. I then attach it to my controller's view essentially having the view reference count and release it as needed.
This concerns me, however, that I have the pointer stored in my member var and that it could be referencing released memory if the count decrements at some point. Is it better practice to instead declare the variable as 'retain' and then in the viewDidUnload method release the member var (or just set it to nil to release and make sure i don't have an address in there)?
Alternatively, could I simply set the member var to nil in viewDidUnload and not make it a retained variable?
Is it better practice to instead declare the variable as 'retain' and then in the viewDidUnload...?
Yes, use retain -- good instinct. In viewDidUnload, you'd typically just set it to nil via the ivar's setter: self.ivar = nil;
I find it easier to be aware of and manage object codependencies explicitly, than to deal with issues related to using assign. You can completely avoid the issues of holding an unmanaged reference.
Arguments can be made that assign would usually be fine here (and it is in some cases), but using assign can complicate object graphs and ownership for anyone working with the class. As program complexity grows (and the libraries you depend on change), it becomes increasingly difficult to track lifetimes of unmanaged references. Things tend to break, or operate differently on different hardware and software combinations. Attempting to manage the lifetime of an unmanaged object over a complex program or in a concurrent context is self abuse. Guaranteeing defined and predictable behavior/operation reduces bug counts.
That's a property, not a "member var" (known in Objective-C as an instance variable or ivar.)
The semantics of a property depend on how that property is going to be used. Generally speaking, you'll want your properties to be retained for the lifetime of your object. If the property is a connected IBOutlet, this will be done for you by the NIB loader; otherwise, you must be explicit and use the retain or copy attribute on the property.
For objects that are expected to own your object, a property should always be marked assign to avoid a retain loop. For example, an object usually owns any object for which it acts as a delegate (usually, but not always--every CS rule has an exception.)
Sometimes I set objects to nil after releasing them to avoid crashes due to unexpected messages sent to dealloc'd objects.
Why doesn't the Objective-c runtime do this automatically when an object is finally dealloc'd?
Because pointers are passed by value and not reference. All dealloc gets is a local copy of the pointer; any changes it makes are discarded. Same goes for C's free and C++'s delete.
How would the runtime be able to track down all such references?
MyClass* a = [MyClass new];
MyClass* aCopy = a;
[a release];
a = nil; // Tidy up
[aCopy crashNowPlease];
Sometimes you can catch this sort of thing with Build & Analyze.
Also, you will be able to use zeroing weak references in the future (or, Mike Ash created such a facility).
In objective-C, the objects are always accessed as pointer.
Setting an object to nil simply change the pointer value, not the object value.
In your method, you have only access to the object's value, not to the pointer pointing to it!
As #David Dunham says, you can have more than one pointer to an object, so how would the compiler knows?
And more than that, to make things easier, imagine the following code :
int a;
int* aPtr = &a;
If you change a value, you can access the changed value via *aPtr right? But you can change a value as long as you want, it won't change aPtr value, as it is not the same variable!
Thus, even if you only have one pointer to your object, if you modify the object's value, you pointer will still point to the same address value!
What you are describing is called a zeroing weak reference. This feature is available in OS X 10.7's Automatic Reference Counting (ARC) runtime. Prior to 10.7, you can use Mike Ash's zeroing weak reference implementation.
Without explicit runtime support (and some small but unavoidable overhead), standard C-style pointers (id in Objective-C is a pointer to a structure) are just a memory address (an integer) and not tracked by the runtime. There's nothing stopping you from making copies of this value elsewhere in memory or from storing the value in an integer of the appropriate size and casting to an id later on (of course if you do any of this, you kill a baby seal). Thus, when an object is dealloc'd there's no way to know where (or how many) references there are to that object.