Do I need to explicitly zero primitives, i.e., set BOOLs to NO, set ints to 0?
Do I need to explicitly assign an NSString* to nil or #""?
I know that pointers must be explicitly set to nil, otherwise they may be filled with garbage. (Or is that only for Objective-C++?)
It depends on what kind of variable you're talking about. Globals, static variables and instance variables are already guaranteed to be initialized to 0.
Local variables are a different story. They are never initialized at all by default, so you shouldn't read their values until you initialize or set them. It isn't strictly necessary to initialize them to 0 specifically. For example, the following code is very redundant:
Controller *controller = nil;
int countOfThings = 0;
controller = [Controller sharedInstance];
countOfThings = controller.totalThings - controller.thingsUsed;
Instead, you should initialize variables to the values you actually want:
Controller *controller = [Controller sharedInstance];
int countOfThings = controller.totalThings - controller.thingsUsed;
It's always good programming practice to initialize primitives, but in general it's only required if you're referring to that variable when there's a chance it wasn't set to anything except garbage memory.
I believe the compiler still throws warnings on "uninitialized variables", but if not, there's definitely a compiler checkbox in XCode for that.
The compiler flag for this is -Wuninitialized, b.t.w.
Related
I would like some help better understanding the memory characteristics of Strings in Cocoa.
The app I am working with uses one view controller and n tool objects. The View controller lives for the life of the program but the tool objects are allocated and released.
Suppose I have a string toolName_ and in my implementation I configure the incoming tool object: if the object does not have a tool name, I want to set the toolName_ string to #"not set". If the tool has a name I want to set the string to the name of the tool.
I would like to know the proper way to store the incoming value into the toolName_ given that sometimes this will be an allocated object and sometimes this will be a constant string.
-(BOOL)setToolObject: ToolObject: obj{
ToolObject someObj = nil;
someObj = [[ToolObject alloc]initWithObject obj];
if(someObj != nil){
if(! [someObj.toolName isEqualToString: #""]){
self->toolName_ = Which method should I use given the above question?
The last instance may have been a constant string but may not have.
[self->toolName_ release] (can I send a release message to a constant
string without causing a problem?)
self->toolName = [[NSString alloc]initWithString:someObj.toolName];
OR
self->tool name = [NSString stringWithString: someObj.toolName];
This method is self releasing but I don't own it and I'm still not sure
what happens to the constant string if it existed. I think I read it's
not recommended to use this on member vars.
}else{
self->toolName_ = #"not set";
}
return YES;
}else{
return NO;
}
}
Advice appreciated.
I highly suggest to (possibly) use ARC, and if you can't use it (or maybe you just want to understand how memory management works?), to don't send retain and release messages from outside the class. Instead you should do this in the accessors.
So you should create a retain or copy property (usually with immutable strings is preferable to use copy, because they may be assigned to mutable strings, so making invalid the assumption that you are working with an immutable - thus thread safe - property).
So in your case I suggest a setter like this one:
- (void) setToolName: (NSString*) toolName
{
if(_toolName== toolName)
return;
[_toolName release];
_toolName= [toolName copy];
}
This way you're doing it fine, you shouldn't be concerned about what is the retain count of the setter argument. In case it is a string literal which has an unknown retain count, the object does not even respond to a release message, so it will stay alive for all the program (unlike it seems it is efficient because it avoids the overhead of creating an object at runtime). If you copy an immutable object (unless it something like a cached NSNumber, or a string literal), the code just does a simple assignment and the retain count gets increased.
So if you just follow the rule of "I retain (or copy) what I need to use, I release what I don't need to use anymore", you're doing it fine and you shouldn't worry about what happens in particular case like with string literals.
I think I have a pretty good understanding of ARC and the proper use cases for selecting an appropriate lifetime qualifiers (__strong, __weak, __unsafe_unretained, and __autoreleasing). However, in my testing, I've found one example that doesn't make sense to me.
As I understand it, both __weak and __unsafe_unretained do not add a retain count. Therefore, if there are no other __strong pointers to the object, it is instantly deallocated (with immutable strings being an exception to this rule). The only difference in this process is that __weak pointers are set to nil, and __unsafe_unretained pointers are left alone.
If I create a __weak pointer to a simple, custom object (composed of one NSString property), I see the expected (null) value when trying to access a property:
Test * __weak myTest = [[Test alloc] init];
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: (null)
Similarly, I would expect the __unsafe_unretained lifetime qualifier to cause a crash, due to the resulting dangling pointer. However, it doesn't. In this next test, I see the actual value:
Test * __unsafe_unretained myTest = [[Test alloc] init];
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: Hi!
Why doesn't the __unsafe_unretained object become deallocated?
[EDIT]: The object is being deallocated... if I try to substitute lines 2 - 3 with NSLog(#"%#", myTest); the app crashes (and an overridden dealloc in Test is being called immediately after the first line). I know that immutable strings will continue to be available even with __unsafe_unretained, and that a direct pointer to the NSString would work. I am just surprised that I could set a property on a deallocated object (line 2), and that it could later be dereferenced from a pointer to the deallocated object it belonged to (line 3)! If anyone could explain that, it would definitely answer my question.
I am just surprised that I could set a property on a deallocated object (line 2), and that it could later be dereferenced from a pointer to the deallocated object it belonged to (line 3)! If anyone could explain that, it would definitely answer my question.
When the object is deallocated it is not zeroed. As you have a pointer to the deallocated object and the property value is stored at some offset to that pointer it is possible that storing and retrieving that property value will succeed after deallocation, it is also quite possible that everything will blow up for some reason or other.
That your code works is quite fragile, try debugging it with "Show Disassembly While Debugging" and stepping through, you'll probably hit an access violation, or take down Xcode itself...
You should never be surprised that strange things happen in C, Objective-C, C++ or any of the family; instead reserve your surprise for so few strange things happening!
Because the constant string in objc is a constant pointer to a heap address and the address is still valid.
edited after comment:
Maybe because the memory at the test objects address hasn't been overwritten and still contains that object? Speculating....
You can see when Test is deallocated by implementing its -dealloc method and adding some simple logging.
However, even if Test is deallocated immediately, the memory it occupied in RAM may remain unchanged at the time you call myVal.
#"hi!" produces a static global constant string instance that is, effectively, a singleton. Thus, it'll never be deallocated because it wasn't really allocated in the first place (at least, it really isn't a normal heap allocation).
Anytime you want to explore object lifespan issues, always use a subclass of NSObject both to guarantee behavior and to make it easy to drop in logging hooks by overriding behavior.
Nothing strange thereā¦
You need to have at least 1 strong reference to object to keep it alive.
Test * anTest = [[Test alloc] init];
Test * __weak myTest = anTest;
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: (Hi)
I'm reading a book on Objective-C and the author said that if local variables aren't assigned a value they will be set to nil, but static variables will be set to zero. So, I set up int a and didn't assign it a value. Then NSLog(#"%i", a) to display it and a was displayed as zero. I was a little confused on that and I was wondering if someone could clarify it for me?
With ARC enabled, your Objective-C object pointer variables will be set to nil regardless of where you create them.
Without ARC, and for built in C types, your variables will not be initialized.
Instance variables of Objective-C objects are always set to 0 (or nil) when you allocate an object.
Statics are set to 0.
I've gotten in the habit of always giving a default value to variables, though. It's been a good habit to have.
No2. Just as in "plain" C, local variables are not assigned a default value. (Although you may get lucky the first time part of the stack is used: do not rely on this!.)
Anyway, nil is 01 -- that is, nil == 0 is always true -- so NSLog("#%i", nil) says "hey, log the argument as an integer", which is ... 0.
Happy coding.
1 See nil in gdb is not defined as 0x0? which covers the technical definition, including the Objective-C++ case, in more detail. Note that the type changes depending upon architecture as well so "#%i" could very well be wrong for a particular system.
2 See wbyoung's answer for ARC-specific rules.
in my objective-c program (or, maybe, in debugging utility) I get a bizarre behavior.
I defined, but not allocated or initialized 4 instances of some class (let it be "Rectangle"):
Rectangle *left, *right, *bottom, *upper;
Right after this line, I expect that for all of my four objects will be null pointers (debugging in Xcode), but for one of them (concretely "upper") exist point to some memory location, and his properties is initialized with random values.
Does it normal behavior? If so, please explain me why. (I am a bit new to objective-c programming)
Objective C does not (in general) guarantee that stack values are zeroed. It does guarantee that all ivars in an object are zeroed. Also, under ARC it does zero stack vars that it knows are objects. So the behavior you are seeing is correct assuming you are not using ARC.
In general, even if you are in an environment that zeros the value you should explicitly zero it in case your code gets reused somewhere else. If there is a constraint your code needs to work you should either satisfy it, test for it at runtime, or test for it at compile time (assert()).
As for why this is the case, it is that way because C behaves that way, and C traditionally has done it because it is bare metals and prefers to let the compiler have a lot of liberty in order to do performance optimizations. Objective C only differs in places where it needs to in order to support its own (supplemental) functionality.
Pro-tip: Never assume anything. It is good practice to initialize all your variables to a known value; in this case, nil.
If you are coming from another high-level language that does initialize variables for you, well... this isn't that language. :-)
You should do this...
Rectangle *left = nil;
Rectangle *right = nil;
Rectangle *bottom = nil;
Rectangle *upper = nil;
which is the same as
Rectangle *left = nil, *right = nil, *bottom = nil, *upper = nil;
Use ARC, its amazing as memory management isn't handled by you anymore!
I've run into some unfamiliar Objective-c memory management code. What is the difference between:
// no property declared for myMemberVariable in interface
id oldID = myMemberVariable;
myMemberVariable = [MyMemberVariable alloc] init];
[oldID release];
and:
// (nonatomic, retain) property is declared for myMemberVariable in interface
self.myMemberVariable = [[MyMemberVariable alloc] init];
Thanks!
The second is technically incorrect, but the first probably stems from someone yet to embrace Objective-C 2.0 property syntax. It was added relatively recently if you're a long-time OS X developer (or an even-longer-time NextStep/OS X developer), so you do see people not using it without gaining any benefit or detriment by not doing so.
So the first is basically the same as:
[myMemberVariable release];
myMemberVariable = [[MyMemberVariable alloc] init];
Given that you have a 'retain' property, the correct version with the setter should be:
// this'll be retained by the setter, so we don't want to own what we pass in
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
In the first example, you've got an instance variable. In the second, a property with auto memory management attributes (as indicated by the retain).
In the first example, you're allocating an object, assigning it to an instance variable, then releasing it. It also appears that you're also leaking the object that was previously assigned to it since you don't explicitly release it. (Maybe it's autoreleased, can't tell here).
In the second example, you're allocating an object, and assigning it to a property that is retaining it. This means you're going to leak it unless you explicitly release/autorelease it.
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
or
MyMemberVariable *m = [[MyMemberVariable alloc] init];
self.myMemberVariable = m;
[m release];
It's much better to use properties as you get (most) memory management for free. For example, you won't have to worry about freeing a reference before assigning a new one.
The first form does not use properties. I don't see a good reason not to do:
[myMemberVariable release];
myMemberVariable = [[MyClass alloc] init];
Since the old value is definitely not the same as the new one, so there is no chance any old value is released before it can be retained again.
Properties have the advantage that, in newer compilers, they are synthesized by the compiler and simply do the right thing, i.e. they know how to retain the new and release the old value, if the type is one that must be retained or copied. This is not necessary for types like int, float, etc., since these are simple value types.
In other words, if you use dot notation, either on self or on some other object, you access the property and in fact call either the getter or setter methods, depending on the direction of assignment.
If you access the ivar (member variable) directly, you don't have the protection from the property and have to code retain/release yourself.
You can also write your own setters and getters, and then you'll also have to take care of memory management, where it applies. It does, however, give you more flexibility. You could log items, check the validity of the input, update internal state variables, etc.