Aren't objective-c pointers nil until when you allocate the memory? - objective-c

I thought that when I declare an object the pointer is still nil until when I allocate memory and initialize it. Instead I run this code and I was surprised to see that it outputs "TRUE":
NSString * aString;
if (aString) {
NSLog(#"TRUE");
}
thanks

It is pointing at an undefined location - it can point to any memory location (even one that you don't have access to.
You should NIL it out when declaring it.

When you allocate an OBJECT the storage is nilled, but when you have an automatic variable it's whatever junk it is.

Related

Autorelease and assigning to nil

How the memory management behave when we assign nil to an autoreleased object? Does it get deallocated instantly or does it deallocated with the autorelease pool ?
For etc,
NSString *myString = [NSString stringWithFormat#"%#","MY_STRING"]; //Autorelease object
myString = nil;//What will happen here ? Does it get deallocated ? Or Will it get deallocated with the autolrelease pool ?
Whenever any local variable is being assigned with nil, then that variable changes its pointing memory to 0x0000000. By this, the value presented at the address before will got unpointed.
And, the function of Autoreleasepool is to free the current running program or project or a particular environment's unreferenced addresses. So, the value which is previously being pointed is freed up by Autoreleasepool.

ARC and __unsafe_unretained

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)

Pointer to BOOL in Objective C

Code:
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
BOOL initial = YES;
[invocation setArgument:&initial atIndex:2];
Question:
Would it be possible to pass YES to setArgument:atIndex: without creating the temporary variable?
I was thinking that maybe there's a language construct I'm not aware of and/or constant in the runtime that is always YES that I can point to.
Thanks!
No, not in any clean, reliable way.
NSInvocation will dereference whatever pointer you send it and copy data of length specified by the method signature out of it. You need to have that information somewhere so you can get an address to it, and having the local variable as you have is the best way to do so.
The answer is no. A pointer must point to an address in memory. So first you must allocate that memory and then send the address of that allocated memory into the method. In the case of a primitive the memory allocated will be on the stack and with an object the memory allocated for the object will be on the heap and the address of that object will be stored on the stack. As for the error you are getting the void* parameter of setArgument:atIndex: seems to want an object and not a primivtive. Have you tried using a NSNumber to represent a bool. NSNumber comes with a numberWithBool: method.
A pointer must point to something(including garbage) or nothing(means the pointer being initialized to NULL). A pointer is an indirect reference to an object. If you don't have such an object for your pointer to point to, you may not need a pointer. You can simply call setArgument:NULL atIndex:2.
The case to use a pointer like that in your code is to pass an output parameter, whose value will be set in the function you call, and in this case, you probably don't need to initialize the parameter before passing it to the function, the function is supposed to take care of assigning correct value to it.
So in your case, if you didn't mean to use a output parameter, you only need to pass the primitive BOOL to the function, no pointer needed.
EDIT
I just took a look at the doc for NSInvocation. The answer is the same as others', NO.
You have to pass a pointer, which must point to an existing object for NSInvocation to work correctly.

Objective-c dealloc of boolean value

How would I dealloc a boolean value?
Deallocing it this way below gives me a warning: Incompatible pointer to integer conversion assigning to 'BOOL' (aka 'signed char') from 'void *'
- (void)dealloc {
self.booleanVar = nil;
[super dealloc];
}
Perhaps I should clarify, this is from a simple class inherited from NSObject.
I'm using the self.var = nil pattern that you see in Cocoa Touch classes. Let's say if it was an NSString* instead should I use self.var = nil or [var release] in the deallocmethod? I'm a little confused here.
You don't need to do it. It is not an object. This also explains the warning, as you're trying to assign a nil pointer (that's a NULL for objects basically) to a non-object.
Regarding your second question, yes. You can think of primitive variables as being part of the object, so when it's deallocated the vars will not exist anymore.
But when you have a NSString * in an object, it's just a pointer to another object. If you dealloc the former, the pointer will be deleted, not the NSString. No one might point to it, it's kind of lost in the air, occupying memory. So, before deleting the pointer, if you won't need the object anymore, you send it a release message. That's done in the dealloc method, since it's called to "delete" and object and thus is a good place to delete also every other object that has no use anymore.
You dont need to dealloc a BOOL, since BOOLs are really just a byte, which is a primitive data type. You only need to dealloc objects which have been allocated to memory.
First of all, if booleanVar is just a plain BOOL value, as in it is declared like so:
BOOL booleanVar;
then you do not need to free up any memory associated with it, since that memory is allocated and freed when the class that holds it is allocated and deallocated. So no code for booleanVar in dealloc will be fine.
However, if you are talking about a pointer for a BOOL, defined like so:
BOOL *booleanVar;
and what you want is to set this variable to a non-value, you should set it equal to NULL instead of nil, since NULL is for value pointers and nil is for object pointers (see: NULL vs nil in Objective-C).
However, if what you want is to free up the memory that the BOOL pointer points to, allocated with malloc or realloc, etc, then try the free() C function (see: http://www.cplusplus.com/reference/clibrary/cstdlib/free/).
What would really clear all this up is if you showed us the property declaration for booleanVar in the class interface, which would tell us exactly what you want to do and you would get an answer with complete certitude.

how to initialize an object(NSObject subclass) at a specific address

Hi I need to initialize an NSObject at a particular location that I specify(through a void* pointer, for example). For a little bit of context, I am writing a sqlite3 aggregate function. To keep temporary results from this function, I have to call a sqlite3_aggregate_context function, which allocates a block of memory for me. I want to store an NSDecimalNumber at this location.
So far I have tried two approaches:
1)allocWithZone, by doing:
void *location = sqlite3_aggregate_context(...); //returns a block of allocated memory of a certain size
NSDecimalNumber *num = [[NSDecimalNumber allocWithZone:NSZoneFromPointer(location)] initWithInt:0];
This does not work because NSZoneFromPointer returns nil. Docs say that the arguments to this function must be a previously allocated pointer, which it is. I dont know if this means allocated using NSZoneMalloc/Calloc.
2)
id location = sqlite3_aggregate_function(...);
location = [[NSDecimalNumber alloc] init];
but this causes some kind of infinite recursion when freeing the memory...not sure what the deal is. A screenshot here:
http://dl.dropbox.com/u/3002073/Public%20Sync/sqlitefunctionissue.png
Any suggestions will be greatly appreciated!
You can't really determine reliably where an object is going to be created in memory. The NSZoneFromPointer fails for you because the sqlite3 API is not using zones to allocate its resources.
If you want to be able to pass a specific location, you should do so using a pointer to the object (so you are storing a pointer to a pointer basically). You can then read this information from your aggregate function and update it accordingly. Just make sure that you don't simply let your object be freed at the end of the call without taking care to release it (or you'll have a leak).
So, for example, you could do something like:
NSDecimalNumber** numberLocation = sqlite3_aggregate_context(...);
*numberLocation = [[NSDecimalNumber alloc] initWithDouble:25.0];
You now have a reference to your object stored in your special memory area and can access it any time:
NSDecimalNumber* storedNumber = *numberLocation;
NSDecimalNumber* computedNumber = [[NSDecimalNumber alloc] initWithDouble:[storedNumber doubleValue] * someComputation];
[storedNumber autorelease];
*numberLocation = computedNumber;
On the other hand, I agree with Mark; maybe this immutable class isn't the best solution to your problem?
Your first version is simply not going to work. NSZoneFromPointer only works when passed a pointer allocated from a zone. It's used so you can allocate an object from the same zone as some other object.
The second version ought to work, though it's difficult to tell without more context. What are you passing to sqlite3_aggregate_context as the size of the memory to allocate? And how are you freeing that memory when you're done?
The second version doesn't work because the "id" type is actually a pointer, so you're pointing it at the memory returned by sqlite3_aggregate_context(), then pointing it at the memory returned by alloc/init. You really need to store a pointer-to-pointer to get that to work the way you want.
NSDecimalNumber is an immutable class, so calling -init on it (as opposed to -initWithDecimal:) is just going to get you some default value. What sort of code are you using to replace the NSNumber with new values as the function progresses?
More to the point, why use NSDecimalNumber at all, as opposed to a C integer, or double, or whatever?