Dynamic Memory

Back

Loading concept...

πŸ—οΈ Dynamic Memory: Your Program’s Personal Warehouse

Imagine you’re running a toy store. Sometimes you need 5 boxes to store toys, sometimes 100! You can’t know exactly how many you’ll need before opening the store. That’s exactly what Dynamic Memory does for your programs!


πŸ—ΊοΈ Memory Layout: Where Everything Lives

Think of your computer’s memory like a big apartment building:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  ← Top (High Address)
β”‚         STACK               β”‚  πŸ₯ž Plates pile here
β”‚   (grows downward ↓)        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                             β”‚
β”‚    (empty space)            β”‚
β”‚                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         HEAP                β”‚  πŸ“¦ Boxes go here
β”‚   (grows upward ↑)          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    Uninitialized Data       β”‚  (global vars = 0)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    Initialized Data         β”‚  (global vars with values)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         CODE                β”‚  πŸ“œ Your program's instructions
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  ← Bottom (Low Address)

Simple Rule: Your program lives in an organized building with different floors for different things!


πŸ₯ž Stack vs πŸ“¦ Heap: Two Ways to Store

πŸ₯ž The Stack (Like a Pile of Plates)

When mom washes plates, she stacks them. The last plate added is the first one taken. That’s the stack!

void makeFood() {
    int plates = 5;    // Put on stack
    int cups = 3;      // Put on stack
}  // Plates and cups automatically removed!

Stack Facts:

  • βœ… Super fast (just add/remove from top)
  • βœ… Automatic cleanup (no mess!)
  • ❌ Fixed size (limited space)
  • ❌ Can’t keep things after function ends

πŸ“¦ The Heap (Like a Warehouse)

Imagine a HUGE warehouse where you can:

  • Request any size box whenever you want
  • Keep boxes as long as you need
  • But you MUST return the box yourself!
int* getBox() {
    int* box = malloc(sizeof(int));  // Get box from warehouse
    *box = 42;
    return box;  // Box stays! We have the key!
}

Heap Facts:

  • βœ… Get any size, any time
  • βœ… Keep it as long as you need
  • ❌ Slower (warehouse manager needs to find space)
  • ❌ You MUST clean up yourself!

🎁 malloc: β€œMay I Have a Box, Please?”

malloc = Memory ALLOCation = β€œGive me this much space!”

#include <stdlib.h>

// Get space for 1 integer
int* one_num = malloc(sizeof(int));

// Get space for 10 integers (an array!)
int* ten_nums = malloc(10 * sizeof(int));

// ALWAYS check if you got the box!
if (one_num == NULL) {
    printf("Warehouse is full! 😱\n");
}

malloc gives you:

  • βœ… Raw space (whatever was there before)
  • πŸ“ A pointer (the β€œkey” to your box)
  • ⚠️ NULL if no space available
graph TD A["You: malloc&#35;40;16&#35;41;"] --> B{Warehouse<br>Manager} B -->|Found space!| C["Here&&#35;39;s your key πŸ“&lt;br&gt;&#35;40;pointer&#35;41;"] B -->|No space!| D["NULL 🚫&lt;br&gt;&#35;40;no box&#35;41;"]

🧹 calloc: β€œClean Box, Please!”

calloc = Contiguous ALLOCation = β€œGive me boxes, but wash them first!”

// Get 5 clean integers (all set to 0!)
int* clean_nums = calloc(5, sizeof(int));

// This is like malloc + memset:
// int* nums = malloc(5 * sizeof(int));
// memset(nums, 0, 5 * sizeof(int));

calloc vs malloc:

Feature malloc calloc
Takes total bytes count Γ— size
Contents garbage πŸ—‘οΈ zeros 0️⃣
Speed faster slightly slower

When to use calloc:

  • Arrays that need to start at 0
  • Structures you want β€œempty”
  • When garbage values are dangerous!

πŸ”„ realloc: β€œI Need a BIGGER Box!”

Your toy collection grew! You need more space! realloc to the rescue!

// Started with 5 toys
int* toys = malloc(5 * sizeof(int));
toys[0] = 1; toys[1] = 2;  // Some toys stored

// Need space for 10 now!
int* bigger = realloc(toys, 10 * sizeof(int));

if (bigger != NULL) {
    toys = bigger;  // Use new, bigger box!
    // Old data (1, 2) is still there!
}
graph TD A["toys β†’ πŸ“¦ size 5&lt;br&gt;[1][2][?][?][?]"] --> B["realloc&#35;40;toys, 10&#35;41;"] B --> C["new β†’ πŸ“¦πŸ“¦ size 10&lt;br&gt;[1][2][?][?][?][?][?][?][?][?]"] C --> D["Old box returned ♻️"]

realloc Magic:

  • βœ… Keeps your old data
  • βœ… Can grow OR shrink
  • ⚠️ Might move your box (new pointer!)
  • πŸ’‘ realloc(NULL, size) = malloc(size)

πŸ—‘οΈ free: β€œI’m Done With This Box”

THE MOST IMPORTANT FUNCTION!

Every malloc/calloc/realloc needs a matching free!

int* data = malloc(100);
// ... use data ...

free(data);    // Return box to warehouse!
data = NULL;   // Forget the old key! πŸ”‘βŒ

Why set to NULL?

free(data);
// data still points somewhere! (Dangerous!)
data = NULL;   // Now it's safely "nothing"

The Golden Rule:

🎯 For every malloc, there must be exactly ONE free!


πŸ’§ Memory Leaks: The Forgotten Boxes

Imagine ordering boxes but never returning them. Soon, the warehouse is full of YOUR boxes that you forgot about!

void leaky_function() {
    int* leak = malloc(1000);
    // Oops! We never freed it!
}  // Function ends, pointer gone, memory stuck!

Every time this runs, 1000 bytes are lost forever (until program ends)!

graph TD A["πŸƒ Run leaky_function"] --> B["πŸ“¦ 1000 bytes allocated"] B --> C["πŸšͺ Function ends"] C --> D["πŸ”‘ Pointer lost!"] D --> E["πŸ“¦ Memory STUCK!&lt;br&gt;Can&&#35;39;t use, can&&#35;39;t free"]

Leak Symptoms:

  • 🐌 Program gets slower
  • πŸ’Ύ Memory usage keeps growing
  • πŸ’₯ Eventually crashes (out of memory!)

How to Prevent:

void safe_function() {
    int* safe = malloc(1000);
    // ... use it ...
    free(safe);     // Return the box!
    safe = NULL;    // Safety first!
}

πŸ’€ Double Free: The Dangerous Mistake

What happens if you return a box that’s already returned? CHAOS!

int* data = malloc(100);
free(data);   // Good! Box returned.
free(data);   // BAD! Box already returned! πŸ’₯

Why is this terrible?

  1. The warehouse might have given that box to someone else
  2. You’re now messing with THEIR box!
  3. Program crashes or worse: security holes!
graph TD A["malloc β†’ πŸ“¦ at address 1000"] --> B["free&#35;40;data&#35;41; βœ…&lt;br&gt;Box 1000 returned"] B --> C["malloc &#35;40;someone else&#35;41;&lt;br&gt;Gets box 1000!"] C --> D["free&#35;40;data&#35;41; again πŸ’₯&lt;br&gt;You free THEIR box!"] D --> E["😱 CRASH or&lt;br&gt;πŸ‘Ύ Security Disaster"]

The Double Free Shield:

int* data = malloc(100);
free(data);
data = NULL;  // πŸ›‘οΈ Shield activated!

// Later...
free(data);   // free(NULL) is safe! Does nothing.

πŸ’‘ Pro Tip: free(NULL) is perfectly safeβ€”it does nothing!


🎯 The Complete Picture

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 1️⃣ malloc: Get raw box
    int* raw = malloc(sizeof(int));
    *raw = 42;

    // 2️⃣ calloc: Get clean boxes
    int* clean = calloc(5, sizeof(int));
    // clean[0] to clean[4] are all 0!

    // 3️⃣ realloc: Resize box
    int* bigger = realloc(clean, 10 * sizeof(int));
    if (bigger) clean = bigger;

    // 4️⃣ free: Return ALL boxes!
    free(raw);
    raw = NULL;

    free(clean);
    clean = NULL;

    // βœ… No leaks! No double frees!
    return 0;
}

πŸ“‹ Quick Reference

Function Purpose Returns Example
malloc(size) Get raw memory pointer or NULL malloc(100)
calloc(n, size) Get zeroed memory pointer or NULL calloc(5, sizeof(int))
realloc(ptr, size) Resize memory pointer or NULL realloc(arr, 200)
free(ptr) Return memory nothing free(arr)

πŸ† Memory Master Checklist

  • [ ] Always check if malloc/calloc/realloc returns NULL
  • [ ] Every allocation needs exactly ONE free
  • [ ] Set pointers to NULL after freeing
  • [ ] Never use a pointer after freeing it
  • [ ] Never free the same pointer twice
  • [ ] Remember: Stack = automatic, Heap = manual

You’ve Got This! πŸš€ Dynamic memory is like being a responsible warehouse manager. Get what you need, use it well, and always return it when done!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.