- Memory Management Basics
- Reference Counting
- For the More Curious: More on Memory Management
For the More Curious: More on Memory Management
Throughout the book, we include "For the More Curious" sections that go into deeper explanations of topics presented in the chapter. These sections are not absolutely essential to get you where you're going, but we hope you'll find them interesting and useful. Because these sections are more in-depth than the chapter, they are often (but not always) more advanced. If you read through one of these sections and feel stupid, don't worry; everyone felt stupid the first couple of times these concepts were presented to them.
In this chapter, we talked about the heap and how every object lives inside this part of memory. There are actually two more parts of memory that serve different purposes: the data segment and the stack. The data segment is where the application executable lives, and all of the instructions that make up your methods and functions live here. This area in memory never changes after an application is launched. The code is loaded into memory once and isn't modified. When you create a literal NSString like so,
NSString *foo = @"A string";
the memory for this string lives in the data segment as well. We still treat it as an object, though, and if another object wants to keep this string, it must copy or retain it.
The stack is an area of memory reserved for handling the calling of functions. (A method is really just a function under the hood.) When you call a function, a chunk of the stack is reserved specifically for that function. We call this chunk a stack frame. The stack frame holds the address of the function that called it so that when the function ends, it can return to the previous function. It also contains any of the arguments passed to the function and a space to store the return value of a function. Additionally, it reserves memory for the local variables of a function.
- (void)fido { int x = 5; NSString *str = [[NSString alloc] init]; // The variable "str" is a local variable and it lives in the stack frame // The string it points to lives on the heap. }
Figure 3.6 Pointer on the stack, object on the heap
When a function exits, the stack frame is destroyed along with all of the local variables it had.
We also made a distinction between instance variables that are pointers to objects and instance variables that are primitives. When we add instance variables to a class, we are increasing the size in memory of an instance of that class by the amount of memory that instance variable needs to store its information.
A pointer instance variable is simply four bytes: the amount needed to hold an address of another object that lives on the heap. A primitive's memory is stored inside that instance, so adding a double, for example, would add 8 bytes to the size of that instance.
A Possession has three pointers instance variables and one int, which are each 4 bytes. Therefore, the Possession is 16 bytes plus the amount of bytes an NSObject needs. Let's pretend an NSObject is also 4, for a total of 20 bytes needed per Possession.
So, when instantiating a Possession, 20 bytes are allocated from the heap. Even if the NSString that is the possessionName of that Possession is 100 bytes (because it has 100 characters), the Possession itself remains 20 bytes. This can help us understand the difference between pointers to objects and objects themselves.