 This time we're going to look at the heap. So the heap is the other region of dynamic data that we have available to us, and starts down here, and it's going to grow upwards. It's primarily used for large data structures or long-term data, but if you had a variably sized data structure, you would also want to put that in dynamic data. Really though, this is a region that's for anything that you don't want to put on your stack. Our stack tends to have a limited amount of space available to it, so large data structures don't really fit well on the stack, and anything that you'd like to persist after your function is completed would also not work well on the stack, because that region of memory will be deallocated. So we stick all that sort of data into the dynamic data area. There are two different methods we can use to manage the heap. We can either use the global pointer, or we can ask our operating system to give us some memory directly. The global pointer is similar to the stack pointer in that it indicates where allocated memory stops and unallocated memory starts. But because we start from the bottom of our dynamic memory and move upwards, we would increment our global pointer to allocate memory. In this case, any addresses in the region of memory where their address is less than the value of the global pointer are considered in allocated memory. Any addresses that are equal to or greater than the global pointer are unallocated. So all of that memory is still available. But the operating system is generally more effective at managing dynamic memory, so we can actually just use a system call to handle this for us. If you think about the sort of stuff that we put on our heap, it all has varying life spans. Some of it may just last a little while, other parts will last a long time. And this can be really hard to actually manage yourself. The operating system though tends to be really efficient at keeping track of which pieces of memory have been used and which pieces haven't, so that when a program or a function comes and says, I'd like some memory, you can find a piece of memory that's sufficiently large and available and allocate that block of memory to the function. Doing this yourself would be really complex because you'd have to keep track of which pieces of memory are in use and which aren't. Keeping track of that fragmentation can be really complex. So it's easier to just let the operating system handle that for you in general. But for our purposes, it won't really matter which of those two methods you use. We're not going to be handling large blocks of memory and most of our programs are going to be relatively small. But if you're building a real program, then chances are you just want to let the operating system do that for you.