There are various programming courses I teach, but I’d have to say that Introduction to Programming using C++ is my favorite. I love building and creating, and when I get those students who want to dabble and learn programming, it’s a great opportunity to build their knowledge so they will have enough fundamentals to ace the next programming level classes. These students have never been exposed to programming, and it’s my opportunity to get them ready for a stringent Computer Science program. It’s almost similar to boot camp, except I am in no way an Army Drill Sergeant.
One of the concepts I dedicate a substantial amount of time on is of course variables, and the different kinds of variables. Except that, I make sure to emphasize the different types of memory being used, because it seems that nowadays with the high powered computing we have, students think we have an infinite amount of storage to our disposal. Where do these variables go when declared? Do they go in some black hole inside our computer until we stop using them? Can I declare all my variables to be of type double, even though I am going to deal with numbers with range 1 – 30,000? There are different types of memory regions in RAM, which are dedicated to certain functions of the program execution cycle. Specifically, one of these regions is called stack memory. Stack memory contains any variable declarations and function calls that are done within a function, which of course include your main function. For example:
This declaration would allocate 4 bytes of stack memory space to be used by your program. Stack memory variables are managed for you, so you don’t have to de-allocate any memory storage once a function exits. Remember your variable declarations lie in the main function, so once your program exits main, then those variables are de-allocated for you along with any other function calls that are done.
Every time you call any functions, they get “pushed” on the stack, and once they return, they are popped off. This is what makes the stack a LIFO – Last In First Out data structure. You call the main function, it gets pushed on the stack, along with any arguments and variable declarations that are done. Remember that the stack is finite, meaning that if you keep pushing items on the stack, you will eventually run into the “stack overflow” problem. The stack size limit depends on the Operating System you’re using. The main thing I want my students to take away is to not go wild when declaring variables, and to engrain efficiency early in their mind when they start programming. Stack memory is not some free for all black hole where we could throw in as many things as we want. Surprisingly, when I have taught other levels programming, even object oriented programming, students were unaware of the stack memory/heap memory concept. Let’s summarize a few easy points:
1. Grows and shrinks in size when pushing and popping functions calls and variable declarations.
2. Self Managed
3. Limitation of size, based on the Operating system you are using
4. once a function is popped off a stack, it’s local variables are popped with it.
Heap memory on the other hand is almost the opposite of stack memory. It’s not a LIFO, and almost chaotic so to speak. Heap memory is larger than Stack Memory and is not managed automatically for you. In C++, once you allocate heap memory, you are responsible for freeing it once you have no use for it. In other languages and frameworks (ex. Java,.NET), the process known as the garbage collector exists to de-allocate any heap memory variables that need to be cleaned up. The heap does not have restrictions on variable size, and are not pushed or popped, just allocated. Performance is a little slower, but that’s hardly a limitation. Object Oriented languages such as Java use heap memory to store objects, and their reference is kept in the stack. What do I mean by reference? Supposed you have the following:
MyObject obj = new MyObject();
obj is a reference variable, or in C++ could be called a reference pointer to MyObject(). The object MyObject() is created with all its properties and methods in heap memory, whereas the reference variable obj is kept on the stack. So when programming in Java, you are essentially programming using pointers, and are making use of heap memory exclusively. This is where the difference between C++ and Java comes into play in that, Java has a garbage collector to clean up all your objects in heap memory which are seldom used, versus C++ where you have no garbage collector and have to use good ol “delete”. A lot of confusion lies when passing objects to other functions, and there’s the misconception that they are passed by reference, but in reality are passed by value. Here are couple of points regarding heap memory:
1. Depending on the programming language, is not self managed to some extent.
2. Limitations are much greater than Stack Memory. There are debates on this, but heap memory still has limitations on allocation, hence “OutOfMemoryException” errors
3. Minor performance issues when reading and writing
4. Memory allocation may not be as efficient, and fragmentation could occur.
Understanding the fundamentals of where variables go when declared are essential when building programs, because it makes you conscious of the fact that even computer systems aren’t a black hole of storage. When building enterprise systems, knowing this concept will help you build more scalable systems.