Asterisk usage in Objective-C: related questions - objective-c

I had a couple questions related to this: Asterisk usage in Objective-C
NSArray array; in a local scope would be an object "allocated" on the stack. NSArray *array; indicates an object backed by a hunk of memory, typically allocated from the heap.
How do you know when something is allocated on the stack and on the heap? Are all local variables on the stack and are all pointers on the heap?
Because you aren't dereferencing the pointer to the object and that pointer to the object is critical within the method implementation itself. When you say...
Huh

How do you know when something is allocated on the stack and on the heap? Are all local variables on the stack …
It doesn't matter. The stack and heap are implementation details; the C and Objective-C languages do not know about them, and you should generally not have any reason to care whether something is on the stack or the heap.
On Mac OS X, local variables are on the stack. But, for almost all purposes, this is of no consequence. Don't worry about it.
… and are all pointers on the heap?
No. Pointers are memory addresses; that's all.
Pointer variables can be anywhere any other variables can, which is to say, anywhere (subject to implementation-defined limitations that you needn't care about, as noted above).
See my pointer tutorial for more information.
Because you aren't dereferencing the pointer to the object and that pointer to the object is critical within the method implementation itself. When you say...
Huh
A pointer is a memory address. As such, it refers to the memory at that address. Dereferencing the pointer is accessing that memory.
You never, ever directly access the memory a Cocoa object takes up. You only send it messages, to either ask it questions or tell it to do things. Thus, you never dereference the pointer.
“…that pointer to the object is critical within the method implementation itself.” means that the object, in its method implementations, will need its own pointer. It's only possible to send a message to a pointer to an object (this detail is usually elided). If you somehow pulled this off, the receiver of the message (that is, the object you messaged) would not have its own pointer.
Suppose it were possible to send a message to a dereferenced object. The norm is still to send messages to pointers to objects, so in all likelihood, the object will still need that pointer to itself—making that hypothetical ability to message a dereferenced object useless.
Since it's useless, they left it out entirely. The object will need its own pointer (the pointer is critical to the object's method implementations), so you can only send a message to its pointer.

The * is the dereference operator for C, C++ and Objective-C. Understanding the dereference operator, and memory management in general is far broader than Objective-C. This is a fundamental skill for any C/C++/Objective-C developer. Have a look at the multitude of intro C tutorials on the net to learn more.
Edit: any tutorial on c pointers will do. Such as this http://home.netcom.com/~tjensen/ptr/pointers.htm

In Cocoa, you'll never use stack allocated objects; ALL objects will be prefaced with a * (remember that the type "id"is really another word for "pointer to SOME object") and created on the heap.
You'll always have this:
NSArray *myArray;
and never this:
NSArray myArray;
You can ignore the second chunk, since you're always dereferencing the pointer.

Hope these naive toy examples can help you.
In C, in a function,
int x; // x is a variable of type int in stack
int *xp; // xp is a variable of type int * (pointer to int) in stack
int *xp2 = (int *) malloc(sizeof(int)); // xp2 is a variable in stack, it points to a memory location(size is of int) in heap
xp = &x; // xp can point to x
xp = xp2; // xp can also point to what xp2 points to
free(xp2); // now xp and xp2 point to a freed memory, BAD to use xp and xp2 now.
int **y; // y is a variable in stack, type is int **
y = (int **) malloc(sizeof(int *)); // allocate a piece of memory in heap, to hold a pointer to int(int *)
*y = (int *) malloc(sizeof(int)); // allocate a piece of memory in heap, to hold an int
**y = 100; // now we can use it
free(*y);
free(y);
In C++, in a function or member function(method),
SomeClass a1; // a1 is an object of type SomeClass in stack
SomeClass *a2 = new SomeClass(); // a2 is a pointer(in stack) pointing to an object(of type SomeClass) located in heap
delete a2;
So in C++, objects can exist in stack or heap
In Java, in a function or method,
SomeClass b1; // b1 is just a reference, no object exists yet
b1 = new SomeClass(); // in java, objects can only exist in heap
int x; // however, primitive types are in stack,
In Objective-C, in a function or method,
SomeClass c1; // you can't do this.
SomeClass *c2 = [[SomeClass alloca] init]; // c1 is a pointer in stack, pointing to an object in heap
[c2 release];

Related

How does compiler allocate memory for Class Objects?

Given the following variable declaration,
Foo* foo;
how is memory actually being allocated?
This is my guess. There are actually two pieces of memory being allocated here.
A 32 bit number representing a memory address stored at foo [The pointer]. How exactly does the compiler mark or signal that the pointer is actually storing a reference to memory that is of type of Foo?
A contiguous memory segment that is uninitialized and typed as Foo. How does it know how much memory to allocate? How does it mark the memory segment as being of type Foo?
The line of code you've given doesn't allocate any memory. At most, it moves the stack pointer sufficiently to make room for a one-word value (though after optimization, it may not even do that).
A 32 bit number representing a memory address stored at foo [The pointer].
By "32 bit number" I assume you mean "a pointer-sized integer" which is 64 bits on most modern processors. This may, if it's not optimized, be aliased to some location on the stack.
How exactly does the compiler mark or signal that the pointer is actually storing a reference to memory that is of type of Foo?
It doesn't signal this, and it doesn't store a reference to memory that is of any type at all. The above line of code just (at most) makes room for a pointer. In ObjC, at runtime there are no object types. Every pointer to an object is considered id. ObjC absolutely does not promise that this represents a "contiguous memory segment" (there are plenty of cases where what you would think of as "the data" is not contiguous). At a deeper level, the processor does not care about "types" at all. There is just memory and pointers (void *) to memory. (At a deeper level than that, there isn't even "memory." There's physical RAM, caches, registers, and many other things that are generally abstracted away, even in C. For more on that, see C is not a Low-Level Language.)
A contiguous memory segment that is uninitialized and typed as Foo. How does it know how much memory to allocate? How does it mark the memory segment as being of type Foo?
This isn't allocated at all by the above line. If you want to allocate memory for Foo, you must call +[Foo alloc]. Since it is a class method on Foo, it knows how much memory Foo requires. Nothing marks that memory of being of any type, and Objective-C does not actually care what type it is. All it cares is that theres a pointer in the right place called the isa pointer that it can use to lookup how to dispatch messages via objc_msgSend.
There are plenty of cases where something called *Foo does not point to a Foo. It's very common that the actual thing pointed to is a toll-free-bridged type, which is a data structure for a completely different type (a CF structure) that happens to have an isa pointer in the right place so that it can pretend to be an ObjC object. All that is required for the system to work is for things to line up "close enough" that objc_msgSend can function. There is no need (or mechanism) for marking memory as being some particular type.
The size of a pointer like Foo * depends on the target platform. On most current Apple platforms, it is 64-bit, but Apple Watch prior to Series 4 is 32-bit.
There are several contexts in which you might write this:
Foo *foo;
You could write this as a global variable, outside of any #interface or #implementation variable declaration and outside of any function. Then, each time the program is started, it allocates space for one pointer and sets that pointer to nil.
You could write this in an #implementation variable declaration, like this:
#implementation MyObject {
Foo *foo;
}
In this case, you have declared an instance variable (or “ivar”). Each time the program creates an instance of MyObject, the instance includes space for one pointer and sets the pointer to nil.
You could write this as a local variable in a function or a method, like this:
- (void)doSomething {
Foo *foo;
}
In this case, you have declared a local variable. Each time the function or method is called, it allocates one pointer in its stack frame and (assuming you compiled with ARC enabled, which is the default) it initializes the pointer to nil.
Note that in all of these cases, foo does not point to an instance of Foo. It points to nil. To make foo point to an instance of Foo, you must set it to reference to Foo that you got from somewhere else. You could get that reference by calling a function or method, like this:
- (void)doSomething {
Foo *foo;
// foo is nil here.
foo = [[Foo alloc] init];
// If [[Foo alloc] init] succeeded, then foo now points to an
// instance of Foo. If [[Foo alloc] init] returned nil, which
// indicates failure, then foo is still nil.
}
Or you could be passed a Foo reference as a function argument:
- (void)doSomethingWithFoo:(Foo *)incomingFoo {
Foo *foo;
// foo is nil here.
foo = incomingFoo;
// foo now points to whatever incomingFoo points to, which should be
// either an instance of Foo, or nil.
}
Or you could get it from some other global, local, or instance variable.
As to “How exactly does the compiler mark or signal that the pointer is actually storing a reference to memory that is of type of Foo”: It doesn't. At compile-time, the compiler knows that foo should only point to a Foo (or nil), and tries to prevent you from assigning it to things that aren't a pointer to Foo. For example, the compiler will issue a warning or an error for this:
Foo *foo = #"hello";
because the compiler knows that an NSString is not a Foo. (I assume you didn't make Foo a typedef or subclass of NSString.)
However, you can override the compiler's type concerns using a cast:
Foo *foo = (Foo *)#"hello";
or by using the id type:
id something = #"hello";
Foo *foo = something;
This compiles, and it runs fine until you try to do something with foo that an NSString doesn't know how to do.
So it's not the compiler that knows “the pointer is actually storing a reference to memory that is of type of Foo”.
The Objective-C runtime knows that the pointer is actually storing a reference to a Foo. To understand how the runtime tracks the type of an object, you first need to know about the Foo class object.
For every Objective-C class in a program, there is, at runtime, one special object called the “class object”. So for NSObject, there is a single NSObject class object, and for NSString, there is a single NSString class object, and for Foo, there is a single Foo class object. Note that in general, a class object is not an instance of itself! That is, the NSString class object is not itself an instance of NSString, and the Foo class object is not itself an instance of Foo.
The Foo class object knows what makes up an instance of Foo:
The superclass of Foo (maybe NSObject, maybe something else).
The name, type, and size of each instance variable of a Foo (except those inherited from the super class of Foo).
The name, type signature, and implementation address of each message understood by a Foo (except those inherited from the superclass of Foo).
The first bytes of every Objective-C object contain a pointer to a class object.1 This pointer is called the isa pointer, and it determines the type of the object. When you use the syntax that sends a message to an object, like [foo length], the compiler generates a call to objc_msgSend. Recall that in [foo length], the object referenced by foo is called the receiver. The objc_msgSend function uses the isa pointer of the receiver to find the receiver's class object. It looks through the class object's table of messages to find the implementation of length and jumps to it. If Foo doesn't define a length message, then objc_msgSend looks in Foo's superclass for the message, and so on up the superclass chain.2
So, it is this isa pointer that determines the type of the object at runtime.
So how does a Foo object get allocated? When you say [[Foo alloc] init], that means “send the alloc message to the Foo class object, and then send the init message to whatever comes back from alloc”. So the Foo class object receives the alloc message. But the Foo class object probably doesn't implement alloc directly. It inherits the NSObject implementation of alloc.
So +[NSObject alloc] actually allocates the memory for a new Foo. As you say, it allocates a “contiguous memory segment”, but it is not “uninitialized and typed as Foo”. It is initialized and type as Foo. The +[NSObject alloc] documentation says:
The isa instance variable of the new instance is initialized to a data structure that describes the class; memory for all other instance variables is set to 0.
You can look at the implementation here. It's the callAlloc function. It uses the standard C library function calloc to allocate memory, and calloc fills the memory to 0. Then it sets the isa pointer.
As to “How does it know how much memory to allocate”: remember that each class object knows all of the instance variables of its instances. So to allocate a Foo, +[NSObject alloc] sums the sizes of all of the instance variables of a Foo, plus the sizes of all of the instance variables of Foo's superclass, recursively to the end of the superclass chain. That tells it how many bytes to allocate. Except that it would be too slow to do that every time it allocates an object. So the program pre-computes the instance size for every class object at startup, and +[NSObject alloc] looks up the precomputed size of a Foo in the Foo class object.
Unless the object is represented as a tagged pointer, but don't worry about that.
If you want to know what happens when objc_msgSend reaches the end of the superclass chain without finding an implementation, read Objective-C Message Forwarding.

Memory allocation of return address in C and Objective-C

In a C function, its locals's memory is allocated when the function is called, and deallocated when function is finished. What about for functions that return a value (e.g. int, string), when and where does the return address's memory is allocated and deallocated, and is it part of the call stack or the callee stack, or something else?
Consider the following example:
int* foo()
{
int _myInt;
return(&_myInt);
}
This example gets me completely confused as of how memory is allocated for the return address that return a pointer. Can someone please explain?
Same for C and Objective-C?
I don't know about Objective-C but, with standard C, return values are typically stored in registers.
When the function returns a pointer type, it is up to the developer to ensure the memory pointed to remains valid after the call.
Consider the following function:
char* GetStr()
{
char buff[50];
strcpy(buff, "Hello, World!");
return buff;
}
This function returns a pointer to local memory, which is deallocated when the function returns. Accessing that memory would constitute a bug with undefined behavior.
This also applies to your example, which is not valid. But since an int can fit in a register, you can simply do return _myInt; and return the value directly.
In Obj-C if you allocated an object via alloc call then the standard practice is to autorelease that object before returning and name the method is such a way that the caller knows that it is getting an autoreleased object. If the caller needs then it can retain that object again.
- (MyClass *)getMyAutoreleasedObject {
MyClass *obj = [[MyClass alloc] init];
return [obj autorelease]; // caller needs to retain if needed
}
And if you do not autorelease then you should name the method in such a way that the caller knows that it must release the returned object. This is a strictly followed convention in Obj-C.
In C, if you allocate memory in stack then that memory is not valid in caller.
int *func() {
int a[100];
return a; // invalid in caller
}
Your example has the same problem. The returned memory is invalid in caller. In this case you can allocate the memory dynamically and the caller needs to free that when done.
int *func() {
int *a = (int *) malloc (100 * sizeof(int));
return a; // caller must free(a)
}
Parameters are passed to a function, and return values are passed back to the caller. How that is done is totally up to the implementation. The language only requires that it works and has nothing to say about how to do it.
On systems with available registers and a hardware assisted stack, these are generally used for passing the values back and forth.
Different types might be treated differently, for example some CPUs have dedicated address registers that hold pointers, or separate floating point registers. In that case values of those types might be handled differently from integer or struct values.
The size of the values passed might also affect it, small value could fit in a register while larger values would not.
Note that a stack is not a requirement for an implementation, it just has to use some other method for organizing values and function calls.
In your example function, any use of the return value whatsoever will invoke undefined behavior, since the lifetime of the pointed-to object has ended. The only safe way to call this function is without using the return value so that it is immediately discarded.

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.

Returning a C-array and memory management

I am slightly bemused by the following property points of class MKMultiPoint in MapKit:
#property (nonatomic, readonly) MKMapPoint *points
It returns an array of struct. One can know the number of elements in the array with the pointCount property.
With my limited knowledge of C, I always thought C-arrays could only be "sort of returned" if passed by reference to a function because the caller is responsible for allocating the memory and then releasing it.
If I were to write a similar property, who would allocate the memory for the array (presumably the callee) and more importantly who would free it (presumably the caller)? That sounds a bit risky to me. Besides, the documentation for the property above doesn't say anything about having to free memory.
What am I missing?
(The sample code is in C).
The good practice is to allocate and free a resource at the same level. There are two ways to define a function that returns an array of things:
// `points` are allocated and freed by the caller.
void MakePoints (MKMapPoint *points, size_t number_of_points);
// usage:
size_t count = 10;
MKMapPoint *points = malloc (sizeof (MKMapPoint) * 10);
MakePoints (points, count);
// Use points
free (points);
// or simply
MKMapPoint points[10];
MakePoints (points, 10);
// Use points
The second way is to let the library function manage the memory:
MKMapPoint *MakePoints (size_t number_of_points);
void FreePoints (MKMapPoint *points);
// Usage:
MKMapPoint *points = MakePoints (10);
// Use points
// The library need not necessarily call free() on points,
// it might reuse it in further calls to MakePoints().
FreePoints (points);
The receiver, in most cases, would handle allocating the memory. Who frees it depends on how you determine ownership. Is the memory allocated by the receiver no longer needed once it's returned? If so, you should probably note in your documentation that the caller needs to free the returned array. If the receiver can reuse the returned memory, leave deallocation to it.
If you wanted to leave it up to the callee to handle memory allocation, you probably wouldn't use a property and instead opt for a message and property like so:
- (NSUInteger) mapPointCount;
- (void) getMapPoints:(MKMapPoint *)pointsOut;
where the sender should provide an existing buffer to store obj.mapPointCount number of MKMapPoints in. Then, you've placed the responsibility for allocation/deallocation on the caller.
If you don't want to go that route, and since the memory in question can't be retained/released/autoreleased by the receiver, I would leave it up to the caller to release it. If you want to make it somewhat clear that the memory is not to be freed, return it with the type const MKMapPoint * and note it in some form of documentation (which should hopefully make it clear that the memory is not owned by whoever accesses the data).
Alternatively, store it in an NSData or something and make it clear that once the next autorelease pool is drained, the pointer is invalid. However, that's a little less friendly, and possibly not safe with garbage collection. Probably wrong about that last bit, but I don't know enough to say, so I'll prefer caution for now.

Does this Objective-C code leak memory?

One thing I'm concerned about is I create two ints, but don't release them. Would it be better to make them NSIntegers?
-(void) flipCoin {
int heads = [headsLabel.text intValue];
int tails = [tailsLabel.text intValue];
if (random() %2 ==1 )
{
heads++;
}
else {
tails++;
}
headsLabel.text = [NSString stringWithFormat:#"%d", heads] ;
tailsLabel.text = [NSString stringWithFormat:#"%d", tails];
}
As sha notes, local variables get allocated in the current stack frame. As soon as the current function call returns, the stack gets "popped", and the memory occupied for the current call is not released so much as abandoned, until it is overwritten by the next call that gets pushed into that part of the stack.
So why do we have to release variables like this:
MyClass *myObject = [[MyClass alloc] init];
Well, you actually don't have to worry about "myObject". It's on the stack, just like your ints, and it will get cleaned up when the current call finishes.
What you have to worry about is the memory that myObject—which is a pointer—points to. It's off somewhere on the heap. Constructing an object involves asking the runtime for some semi-permanent place to put it; that process returns a memory address, which your pointer stores.
alloc and release are Objective-C idioms that largely replace C's malloc() and free() functions, but all of them ultimately are asking the computer to set aside memory on the heap, and all of that memory must ultimately be returned, either through an autorelease pool, a release message, or a free() call.
int is what is known as a primitive type. It is not a pointer to an Objective-C object so you cannot release it. You can't even send a message to it.
NSInteger is also a primitive type in the sense that it is a typedef to a primitive type (long usually). So you can't release that either.
What do you need to release? You need to release any object you obtained by sending new, alloc or a method containing copy. You also need to release objects to which you have sent retain. So all of the local variables in the following must be released:
-(void) foo
{
NSString* aString = [[NSString alloc] init];
NSString* aString2 = [aString copy];
NSString* aString3 = [someOtherString retain];
NSString* aString4 = [#"some string" copy];
}
NB due to implementation details, you would actually get away with not releasing the aString4 but you don't need to worry about it.
No. Your heads and tails variables are local and stored on the stack. This won't cause a leak. Your two NSString assignments near the bottom are created using convenience constructors and will be autoreleased for you.
All default datatypes (int, char, BOOL, etc) are automatically managed for you, and do not (and cannot) be released (for all intents and purposes).
NSIntegers behave likewise, as they are just signed ints (or signed longs on 64-bit machines).
Objects you initialize, however, like NSString or NSArray will usually have to be released (unless they are autoreleased, like the NSStrings at the bottom of your code). If you ever call -alloc and -init on something, you will have to later release it. If you ever doubt whether a method returns an autoreleased object, just read the documentation (it will tell you).
Also, if you want to read up on memory management, there are plenty of wonderful sources that will teach you (Google is a great place to start!), and if you ever think that your code leaks memory, run it through Instruments, and you'll be able to tell...