C Program Memory Layout
See how C programs are organized in RAM! Learn about Stack, Heap, Data, BSS, and Text segments. Essential for understanding memory.
Track Your Progress
Sign in to save your learning progress
What You Will Learn
- ✓Visualize the 5 memory segments
- ✓Know what goes in Stack vs Heap
- ✓Understand global vs local variable storage
- ✓Use size command to check segment sizes
?Why Understand Memory Layout?
As a C programmer, understanding memory layout is essential for:
Debugging Crashes
"Segmentation fault" and "Stack overflow" errors make sense when you understand where things live in memory.
Writing Fast Code
Stack allocation is faster than heap. Knowing when to use each can dramatically improve performance.
Avoiding Memory Leaks
Understanding heap memory helps you properly allocate and free memory without leaks.
Security
Buffer overflows and stack smashing attacks exploit memory layout. Understanding protects you.
Real-world impact: In interviews at companies like Google, Microsoft, and Amazon, understanding memory layout is often tested. Systems programmers, embedded developers, and game developers must know this.
01Introduction to Memory Layout
What is Memory Layout?
When you run a C program, the operating system loads it into RAM (Random Access Memory). The memory is organized into distinct segments, each with a specific purpose. Understanding this layout helps you write efficient code and debug memory issues.
Think of it Like an Office Building:
The 5 Memory Segments
Text
Code
Read-only
Data
Initialized
Globals
BSS
Uninitialized
Auto = 0
Heap
Dynamic
malloc()
Stack
Local/Calls
LIFO
02Memory Layout Diagram
Memory Layout (Low Address → High Address)
argc, argv, environment
Local variables, function calls
malloc(), calloc(), dynamic memory
Uninitialized global/static variables
Initialized global/static variables
Compiled machine instructions
Key Insight
Stack grows DOWN (toward lower addresses) while Heap grows UP (toward higher addresses). They grow toward each other from opposite ends!
03Text Segment (Code Segment)
What is the Text Segment?
The Text Segment stores your compiled code — the machine instructions (binary) that the CPU executes.
| Property | Value |
|---|---|
| Contains | Machine code (compiled instructions) |
| Permission | Read-only (execute) |
| Location | Lowest memory addresses |
| Why Read-only? | Prevent accidental modification of code |
1#include <stdio.h>23// All this code goes to TEXT segment4int add(int a, int b) {5 return a + b; // Instructions stored in TEXT6}78int main() {9 int result = add(5, 3); // Call instruction in TEXT10 printf("Sum: %d\n", result);11 return 0;12}Remember: Your actual printf(), add(), and main()function instructions are stored here as binary code!
04Initialized Data Segment
What is the Data Segment?
Stores global and static variables that are initialized with a value by the programmer.
Read-Write Section
Variables that CAN be changed
int score = 100;
static float rate = 0.05;
Read-Only Section
Constants (cannot be changed)
const int MAX = 100;
char *msg = "Hello";
1#include <stdio.h>23// Global initialized variables → DATA segment4int playerScore = 500;5char *gameName = "Space Invaders";6const int MAX_LIVES = 3;78int main() {9 // Static initialized variable → DATA segment10 static int level = 1;11 12 printf("Game: %s\n", gameName);13 printf("Score: %d, Level: %d\n", playerScore, level);14 printf("Max Lives: %d\n", MAX_LIVES);15 16 return 0;17}Game: Space Invaders
Score: 500, Level: 1
Max Lives: 3
05BSS Segment (Uninitialized Data)
What is BSS?
BSS (Block Started by Symbol) stores global and static variables that are NOT initialized (or initialized to 0). The kernel automatically sets them to 0 before execution.
Automatic Initialization
Variables in BSS are automatically initialized to:
• Numbers: 0
• Pointers: NULL
• Characters: '\0'
1#include <stdio.h>23// Uninitialized global → BSS (auto-initialized to 0)4int totalUsers;5char username[50];6float balance;78int main() {9 // Uninitialized static → BSS (auto-initialized to 0)10 static int loginCount;11 12 printf("Total Users: %d\n", totalUsers); // 013 printf("Login Count: %d\n", loginCount); // 014 printf("Balance: %.2f\n", balance); // 0.0015 16 // Empty string (first char is '\0')17 printf("Username: '%s'\n", username);18 19 return 0;20}Total Users: 0
Login Count: 0
Balance: 0.00
Username: ''
BSS vs Data
int x; → BSS (uninitialized, auto = 0)int x = 0; → DATA (explicitly initialized)int x = 5; → DATA (explicitly initialized)
06Heap Segment (Dynamic Memory)
What is the Heap?
The Heap is for dynamic memory allocation — memory you request at runtime using malloc(), calloc(), and realloc().
| Property | Value |
|---|---|
| Grows | Upward (toward higher addresses) |
| Managed By | Programmer (malloc/free) |
| Lifetime | Until free() is called |
| Size | Limited by available RAM |
1#include <stdio.h>2#include <stdlib.h>34int main() {5 // Allocate array on HEAP6 int *scores = (int *)malloc(3 * sizeof(int));7 8 if (scores == NULL) {9 printf("Memory allocation failed!\n");10 return 1;11 }12 13 // Use heap memory14 scores[0] = 85;15 scores[1] = 92;16 scores[2] = 78;17 18 printf("Scores: %d, %d, %d\n", scores[0], scores[1], scores[2]);19 20 // Free heap memory21 free(scores);22 scores = NULL;23 24 return 0;25}Scores: 85, 92, 78
07Stack Segment
What is the Stack?
The Stack stores local variables, function parameters, and return addresses. It follows LIFO (Last In, First Out).
| Property | Value |
|---|---|
| Grows | Downward (toward lower addresses) |
| Contains | Local variables, parameters, return address |
| Managed By | Compiler (automatic) |
| Lifetime | Until function returns |
1#include <stdio.h>23void greet(char *name, int age) {4 // name and age are on STACK (parameters)5 char message[50]; // Local array on STACK6 7 printf("Hello %s, you are %d years old!\n", name, age);8}910int main() {11 int year = 2024; // Local variable on STACK12 char city[] = "NYC"; // Local array on STACK13 14 greet("Alice", 25); // New stack frame created15 16 // After greet() returns, its stack frame is removed17 printf("Year: %d, City: %s\n", year, city);18 19 return 0;20}Hello Alice, you are 25 years old!
Year: 2024, City: NYC
Stack Frame During greet() Call
← When greet() returns, its frame is popped
08Stack vs Heap Comparison
How Stack and Heap Grow
Grows DOWN toward heap
↕ Free Space ↕
If stack and heap meet = crash!
Grows UP toward stack
| Feature | Stack | Heap |
|---|---|---|
| Grows | Downward ↓ | Upward ↑ |
| Speed | Very Fast | Slower |
| Managed By | Compiler (auto) | You (manual) |
| Size Limit | Small (~1-8 MB) | Large (GBs) |
| Allocation | int x; (automatic) | malloc()/free() |
| Risk | Stack Overflow | Memory Leak |
| Use When | Size known at compile | Size unknown/large |
Quick Decision Guide
- • Stack: Small, temporary data (local variables, function params)
- • Heap: Large data, unknown size, or needs to persist after function returns
09Checking Segment Sizes (Linux)
On Linux, use the size command to see the size of each segment:
1# Compile the program2gcc program.c -o program34# Check segment sizes5size program67# Output example:8# text data bss dec hex filename9# 1418 544 8 1970 7b2 programExperiment: Watch Segments Grow
Add Initialized Global
int score = 100;
→ Data segment grows
Add Uninitialized Global
int count;
→ BSS segment grows
10Complete Example: All Segments
1#include <stdio.h>2#include <stdlib.h>34// DATA segment (initialized globals)5int maxPlayers = 4;6const char *version = "1.0";78// BSS segment (uninitialized globals)9int highScore;10char playerName[20];1112void showInfo(int level) {13 // STACK: level parameter, bonus local variable14 int bonus = level * 100;15 printf("Level %d bonus: %d\n", level, bonus);16}1718int main() {19 // STACK: local variables20 int currentLevel = 5;21 22 // HEAP: dynamic allocation23 int *inventory = (int *)malloc(10 * sizeof(int));24 25 printf("=== Memory Segments Demo ===\n");26 printf("Max Players: %d (DATA)\n", maxPlayers);27 printf("High Score: %d (BSS, auto=0)\n", highScore);28 29 showInfo(currentLevel);30 31 // Clean up heap32 free(inventory);33 34 return 0;35}=== Memory Segments Demo ===
Max Players: 4 (DATA)
High Score: 0 (BSS, auto=0)
Level 5 bonus: 500
Where Each Variable Lives
| Variable | Segment | Why? |
|---|---|---|
| maxPlayers | DATA | Global, initialized |
| version | DATA (RO) | String literal (const) |
| highScore | BSS | Global, uninitialized |
| playerName | BSS | Global array, uninitialized |
| currentLevel | STACK | Local to main() |
| level, bonus | STACK | Local to showInfo() |
| inventory | HEAP | malloc() allocated |
!Code Pitfalls: Common Mistakes & What to Watch For
Copied code often provides code without explaining where variables actually live in memory, leading to misunderstandings about scope and lifetime.
If you search online "what's the difference between a global and local variable?", it will explain scope, but often fails to mention that they reside in completely different memory segments (DATA/BSS vs Stack) with different lifetimes and initialization behavior.
The Trap: Online sources are good at syntax but often abstract away the underlying memory model. They might not explain why returning a pointer to a local variable is dangerous (it points to deallocated stack memory) or why uninitialized global variables are zero (BSS segment behavior) while local variables contain garbage.
The Reality: Understanding C's memory layout (Text, Data, BSS, Heap, Stack) is crucial for writing safe, efficient code. It explains variable lifetimes, initialization rules, and common bugs like stack overflow and dangling pointers. Copying code without grasping this model leads to code that works by accident rather than by design.
12Frequently Asked Questions
Q:What happens when stack and heap meet?
A: Stack overflow or heap exhaustion! The stack grows down, heap grows up. If they collide, you're out of memory. Deep recursion or large local variables cause stack overflow; many allocations cause heap exhaustion.
Q:Why are global variables in BSS initialized to zero?
A: BSS only stores size, not data — the OS zeros that memory when loading the program. This saves executable file size (no need to store thousands of zeros) and provides security (no leftover data from previous programs).
Q:Why is the text segment read-only?
A: Security! If code could modify itself, malicious input could inject and execute arbitrary code. Read-only text prevents this. It also allows sharing — multiple instances of the same program share one copy in memory.
Q:How can I see the memory layout of my program?
A: Use size program to see section sizes. On Linux, check /proc/PID/maps for runtime mapping. Tools like objdump andreadelf show detailed segment info.
12Summary
Key Takeaways
- •TEXT: Compiled code (read-only)
- •DATA: Initialized global/static variables
- •BSS: Uninitialized global/static (auto = 0)
- •HEAP: Dynamic memory (malloc), grows UP
- •STACK: Local variables, function calls, grows DOWN
int globalInit = 5;
int globalUninit;
int localVar = 10;
int *ptr = malloc(4);
Test Your Knowledge
Related Tutorials
Static Keyword in C
The static keyword gives variables memory that persists between function calls. Learn how static creates "sticky" variables and private globals.
Dynamic Memory Allocation
Allocate memory at runtime! Use malloc, calloc, realloc, and free. Create arrays whose size you don't know until the program runs.
Memory Alignment & Padding
Understand why compilers add padding to structures. Learn about memory alignment requirements, how to minimize padding, and packed structures for embedded systems.
Have Feedback?
Found something missing or have ideas to improve this tutorial? Let us know on GitHub!