Why a pointer to user-defined object does not hold the same address in the memory as the user-definded object itself - objective-c

I am leaning blocks In objective-c, I wanted to understand the concept behind the pointers from the perspective of objective-c.
given the code below, I expected that the the 3 statement to display the same result or at least the sam memory address. At least because, the pointer
meAsImpl refers/points/observs the memory location of the user-defined object MeAsImpl
Hence, the 3 NSLog statement should display the same results
The out put of the code are as follows:
<MeAsImpl: 0x600000194120>
<MeAsImpl: 0x60000019f240>
<MeAsImpl: 0x60000019f240>
Please let me know why the first value differs to the subsequent two values
code:
MeAsImpl *meAsImpl = [[MeAsImpl alloc] init];
NSLog(#"%#", meAsImpl);
NSLog(#"%#", MeAsImpl.alloc);
NSLog(#"%#", MeAsImpl.alloc.init);

Every time you call alloc, new memory address allocates for the caller. init just initialized the already allocated memory, so the address wont change on init
You use alloc two times, you get two memory addresses.

Related

What are difference between *a and **a in objective-c object?

I write the following code:
NSArray *array = #[#1, #2];
How to output *array and **array, and what is the difference between them?
There are some answers, but I think none of them are a real help to you, because they describe the technical meaning.
Let's have a look to the first declaration:
NSArray *array …;
When somebody talks about this code, you will find statements like array is an instance object of NSArray. Even every experienced Objective-C developer knows the real meaning of this statement, it is simply wrong. What is the correct statement?
A. The instance object of NSArray
An instance object has a state, basically a set of data stored. To do so, it needs memory, which is reserved while object creation. You do not deal directly with that, but it is done inside +alloc. This is done explicitly at runtime while the program is running ("on heap", "heap allocation").
… [NSArray alloc] … // Get memory for an instance object of type NSArray
You address such an object solely via its address, the number of the first memory cell of the occupied memory area. (Every memory cell has a number, called the address. Yes, it is similar to addressing inhabitants in a house via the number of the house in a street. Therefore you can imagine the memory as a very, very long street.)
But an identifier like array only exists at compile time and is removed when the program is compiled. Therefore it is obvious that an identifier like array never denotes an instance object.
Short version: An instane object is an area of memory and is solely addressed via the number of the first memory cell (location).
B. A pointer to an instance object (reference)
But if an instance object is addressed via its number at runtime, how can my code deal with it? The trick is that the number is stored in a variable. (Looking to the C standard that is not completely correct. They say that it is stored in an object. But these objects has nothing to do with Objective-C objects and I will focus on variables, a subtype of objects.)
So you can have a variable storing the memory location of an instance object. Such a variable is called a pointer variable. It is declared with an extra *. So
NSArray * array;
means: A pointer variable with the identifier array that stores the location of an instance object of the type NSArray.
(Addresses are numbers. They are integral numbers. Therefore there is a connection between pointer variables and integers. And you can apply calculations to that numbers, called "pointer arithmetics". In some Situations this is important for C developers, but not for you as an Objective-C developer.)
The memory for this variable is not reserved explicitly with +alloc, but implicitly when you enter the area of your code, where the variable is declared. (Not completely correct again, but enough for this explanation.) So let's have a look again to a very boiled down version of object creation:
- (void)method
{
NSArray *array = [NSArray alloc];
}
The right side of this statement reserved memory for the object instance and returns a number, the address of the memory area. This number is assigned to a reference called array. The memory for that reference (it stores something, so it needs memory) is reserved implicitly via its definition.
Pointers to objects are usually called references.
Short version: So array is a reference to an instance object, storing the address of the instance object.
C. A pointer to a pointer to an instance object
Okay, we have an instance object that occupies memory to store the object state, addressed via its memory location (address). Then we have a variable that stores that address, the reference array. You can address that via its identifier.
But sometimes it is useful – I will have an example below – to address the reference variable via its address, too. You can get the address of a variable using the address operator &.
&array
What you get is: The address of a variable storing the address of an instance object. The type of such a double indirection ("address of … address of …") is
NSArray ** array;
This is, because in a variable definition the * means "address of".
Short version: A pointer to a reference is a variable that stores the address of a variable that stores the address of an instance object. It is declared with **. (Yes, you can have more level of indirections … No, that is not easier to understand.)
D. Use cases for pointers to references
Usually you do not need such double indirections in Objective-C. But there is one important use case, an error out parameter. To understand that, we will look at a method with a single indirected parameter as you know is:
- (BOOL)methodThatCanProduceAnError:(NSError*)error
{
…
error = [NSError alloc] … // Create an error object and store its address to the reference variable error.
return NO;
…
}
This method should emit an error via its error parameter.
You "call" such a method with code like that:
…
NSError *error; // A reference variable pointing to an instance object of type NSError
error = nil; // I do not have an error, so it points to "nothing".
[anInstance methodThatCanProduceAnError:error];
What happens? You pass the address of an instance object to that method as an argument. You pass nil for saying "I have no error". This is quite clear, because the method should pass out a reference to an instance object.
So the interesting part is inside the method, when it creates the error object and tries to pass it out. This does not work!
In Objective-C arguments are always passed by value. That means, that the value of the argument in the "calling code" is taken and assigned to a new variable inside the "called code". This new variable is called a parameter variable. When the method tries to change the value of the variable
error = [NSError alloc] … // Create an error object and store its address to the reference variable error.
it solely changes the value of the variable copy inside the method. The new reference will never find the way out of the method and the variable error in the calling code is left untouched. In the "calling code", error still has its old nil value.
So we need a way to change the content of the reference inside the "calling code". We do that by passing the address of the reference to the method:
- (BOOL)methodThatCanProduceAnError:(NSError**)error // double indirection
{
…
*error = [NSError alloc] … // *error is a reference to an object
return NO;
…
}
First in the method head we declare a parameter variable that is double indirected: The address of a reference. Second we assign the address of an instance object to the location, error points to. (This is done by the *.) The assignment is not done to the parameter variable, but to the location, the parameter variable points to.
Therefore we can pass the address of the reference:
NSError *error; // A reference variable pointing to an instance object of type NSError
error = nil; // I do not have an error, so it points to "nothing".
NSError ** pointerToError = &error; // The address of the reference.
[anInstance methodThatCanProduceAnError:pointerToError];
Now the method changes the contents of the reference variable. The error is passed out.

Archiving an object and then unarchiving it

NSString *cachePath= [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
cachePath= [cachePath stringByAppendingPathComponent:#"nerd.archive"];
// Load the cached channel
RSSChannel *cachedChannel= [NSKeyedUnarchiver unarchiveObjectWithFile:cachePath];
NSLog(#"unarchived data- %# %p, x value- %d",cachedChannel,cachedChannel,cachedChannel.x);
// if one hasn't already been cached, create a blank one to fill up
if (!cachedChannel) {
cachedChannel= [[RSSChannel alloc] init];
NSLog(#"cachedChannel initialised- %# %p",cachedChannel,cachedChannel);
cachedChannel.x=5;
}
In the above code-snippet, the pointer variable cachedChannel is assigned with the return value of unarchiveObjectWithFile: message. Now obviously in the first run, this would return nil but the pointer will be initialized later on in the “if-statement”. Lets say the cachedChannel var is something like
cachedChannel= [RSSChannel:0X123ff]
After the code has gone through its first run, the object assigned to cachedChannel would become serialized.
When i run the test project the second time and the unarchiveObjectWithFile: message is passed so that the serialized object is returned and assigned to the cachedChannel pointer var, it shows up as a different object with a different object-id.
Instead of cachedChannel pointing to [RSSChannel:0X123ff] object, it is now holding some other object like [RSSChannel:0X445ee]
How could this be possible?? Shouldn’t the object that was serialized before be the one to be unarchived later on with the same object-id residing in the same heap memory location?
How could this be possible?? Shouldn’t the object that was serialized before be the one to be unarchived later on with the same object-id residing in the same heap memory location?
Not at all. This is, as you say, happening later. And at this later time, the memory situation is completely different. Think of it this way: if you have code that creates an object from scratch, e.g. [[MyObject alloc] init], and you run the app today and then quit it and run the app again tomorrow, those two instances of MyObject, even though they play the very same role in the life of the app, will have two different memory addresses.
Moreover, what we are creating as we unarchive the object is a different instance from the one that was archived - identical, in whatever ways you have specified while archiving / unarchiving, to the original, but a different instance. Think of it this way: archive-unarchive is an elaborate way of making a copy of the object - and two copies of one instance are, obviously, two different objects.
After all, you could archive the object, hang on to the original, and immediately unarchive the archived object. That would be two different objects. But they could not possibly live at the same memory address!
It sounds like you may be trying to use the memory address as some sort of unique identifier. Beware of that. If a thing needs a unique identifier, give it a unique identifier as a property. Don't rely on the memory address at runtime for anything, except during debugging to confirm that two instances are one and the same instance.

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

When and when to not allocate memory to objects

NSArray *array = [dictionary objectForKey:#"field"];
and
NSArray *array = [[NSArray alloc] initWithArray:[dictionary objectForKey:#"field"]];
I see both kind of approaches very frequently in objective C code.
When tried to understand, I found both of them used in similar situation too, which makes contradiction. I am not clear on when I should use 1st approach and when 2nd one?
Any idea?
Detailed explanation and useful references are moms welcome.
First off, those two examples are doing slightly different things. One is retrieving something from an existing dictionary and one is creating a new array by retrieving something from an existing dictionary (the value of that key is an array).
But, if you're asking the difference between getting objects by alloc vs. convenience methods. ([NSString alloc] init vs [NSString stringWith ...), by convention, you own anything that you call alloc, new copy or mutableCopy on. Anything that you call that is not those, is autoreleased.
See the memory guide here. Specifically, look at the rules.
Getting an autoreleased object means it will go away at some point in the near future. If you don't need to hold onto outside the scope of that function, then you can call autorelease on it or use one of the convenience methods that's not alloc, etc...
For example:
// my object doesn't need that formatted string - create the autoreleased version of it.
- (NSString) description {
return [NSString stringWithFormat:#"%# : %d", _title, _id];
}
// my object stuffed it away in an iVar - I need the retained version of it. release in dealloc
- (void) prepare {
_myVal = [[NSString alloc] initWithFormat:"string I need for %d", _id];
}
In the first example, I created a convenience methods for others to call, my class doesn't need that object beyond the scope of that method so I create the autoreleased version of it and return it. If the caller needs it beyond the scope of his calling method, he can retain it. If not he can use it and let it go away. Very little code.
In the second example, I'm formatting a string and assigning it to an iVar variable that I need to hold onto for the lifetime of my class so I call alloc which will retain it. I own it and releasing it eventually. Now, I could have used the first version here and just called retain on it as well.
You have a fundamental misunderstanding of allocations versus instance methods.
The first example, NSDictionary's -objectForKey method, returns id, not an instance of NSDictionary, therefore it does not allocate or initialize the variable.
The second, however is the classic retain part of the retain-release cycle.
The two methods are fundamentally equal (if we are to assume that array is alloc'd but empty in the first, and nil in the second), and both get ownership of the array object. I would go with the second, as it guarantees a reference, and it's shorter.
What I think you're confusing this with are new and convenience methods. Convenience methods (like NSNumber's +numberWithInt:, NSString's +stringWithFormat:, and NSMutableArray's +array), return an autorelease instance of the class (usually). New takes the place of alloc and init in just one word.

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?