๐ช What is Dynamic Memory Allocation?
Dynamic memory allocation means allocating memory during program execution (runtime) instead of compile-time.
Unlike static memory (like arrays), where you must know the size ahead of time, dynamic memory lets you request memory when needed โ and free it later.
๐ฏ Why Use Dynamic Memory Allocation?
Static Memory ( | Dynamic Memory ( |
|---|---|
Fixed size at compile-time | Flexible size at runtime |
May waste memory | Efficient usage |
Stack allocation | Heap allocation |
Limited size | Much larger space |
๐งฐ Functions Used (All from <stdlib.h>)
Function | Description |
|---|---|
| Allocates memory block |
| Allocates and initializes memory |
| Resizes previously allocated memory |
| Frees previously allocated memory |
๐ฆ malloc() โ Memory Allocation
๐ Purpose:
Allocates a specified number of bytes in memory and returns a void pointer to the first byte of the allocated space.
๐ก Characteristics:
Memory is uninitialized (contains garbage values).
Returns
NULLif memory allocation fails.
๐งช Syntax:
ptr = (cast_type *) malloc(size_in_bytes);โ Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(sizeof(int) * 5);
// Checking if failed or pass
if (ptr == NULL) {
printf("Allocation Failed");
exit(0);
}
// Populate the array
for (int i = 0; i < 5; i++)
ptr[i] = i + 1;
// Print the array
for (int i = 0; i < 5; i++)
printf("%d ", ptr[i]);
return 0;
}๐ sizeof(int) is used to calculate size in bytes, ensures portability.
โ ๏ธ Important:
Always check if the returned pointer is
NULL.Cast is optional in C but required in C++.
๐ฆ calloc() โ Contiguous Allocation
๐ Purpose:
Allocates memory for an array of elements and initializes all bytes to zero.
๐ก Characteristics:
Useful when you want a clean memory block.
Slower than
malloc()because of the initialization step.
๐งช Syntax:
ptr = (cast_type *) calloc(num_elements, size_of_each);โ Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)calloc(5, sizeof(int));
// Checking if failed or pass
if (ptr == NULL) {
printf("Allocation Failed");
exit(0);
}
// No need to populate as already
// initialized to 0
// Print the array
for (int i = 0; i < 5; i++)
printf("%d ", ptr[i]);
return 0;
}๐ realloc() โ Reallocation of Memory
๐ Purpose:
Changes the size of a previously allocated memory block (malloc or calloc) without losing existing data (if possible).
๐ก Characteristics:
Expands or shrinks the memory block.
May move memory to a new location.
If it fails, it returns
NULLwithout freeing the original block.
๐งช Syntax:
ptr = realloc(ptr, new_size);โ Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(5 * sizeof(int));
// Resize the memory block to hold 10 integers
ptr = (int *)realloc(ptr, 10 * sizeof(int));
// Check for allocation failure
if (ptr == NULL) {
printf("Memory Reallocation Failed");
exit(0);
}
return 0;
}โ free() โ Free Allocated Memory
๐ Purpose:
Releases dynamically allocated memory back to the system.
๐ก Characteristics:
Helps prevent memory leaks.
Once freed, accessing the pointer is undefined behavior.
๐งช Syntax:
free(ptr);โ Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)calloc(sizeof(int), 5);
// Do some operations.....
for (int i = 0; i < 5; i++)
printf("%d ", ptr[i]);
// Free the memory after completing
// operations
free(ptr);
return 0;
}After calling free(ptr), the pointer ptr becomes a dangling pointer unless set to NULL.
<div class="infographic-calloc">
<style>
.infographic-calloc {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--code-bg: #1e1e2e;
--code-text: #d4d4e0;
--syn-keyword: #c586c0;
--syn-func: #dcdcaa;
--syn-comment: #6a9955;
--warn: #b45309;
--warn-soft: #fdf0dc;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
}
.infographic-calloc[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--code-bg: #0d0d14;
--code-text: #d4d4e0;
--warn: #e0a458;
--warn-soft: #3a2c14;
--ok: #5cd6a0;
--ok-soft: #16342a;
}
.infographic-calloc {
box-sizing: border-box;
max-width: 780px;
margin: 0 auto;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', -apple-system, sans-serif;
padding: 0 clamp(1rem, 4vw, 2.25rem) 1.25rem;
}
.infographic-calloc *, .infographic-calloc *::before, .infographic-calloc *::after {
box-sizing: border-box;
}
.infographic-calloc h1 {
font-family: 'Fraunces', Georgia, serif;
font-weight: 600;
font-size: clamp(1.4rem, 3.5vw, 1.9rem);
margin: 1.25rem 0 0.2rem;
text-align: center;
}
.infographic-calloc .subhead { color: var(--ink-soft); font-size: 0.85rem; margin-bottom: 1.2rem; text-align: center; }
.infographic-calloc .chip-row { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.45rem; margin-bottom: 1.1rem; }
.infographic-calloc .chip {
all: unset;
cursor: pointer;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.82rem;
font-weight: 600;
padding: 0.42rem 0.9rem;
border-radius: 20px;
border: 1px solid var(--line);
color: var(--ink-soft);
transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.infographic-calloc .chip:hover { border-color: var(--accent); }
.infographic-calloc .chip.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }
.infographic-calloc .code-panel {
background: var(--code-bg);
color: var(--code-text);
border-radius: 8px;
padding: 0.65rem 0.9rem;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
line-height: 1.6;
margin-bottom: 0.9rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
max-width: 100%;
}
.infographic-calloc .code-panel .code-line { display: block; white-space: pre; }
.infographic-calloc .syn-keyword { color: var(--syn-keyword); }
.infographic-calloc .syn-func { color: var(--syn-func); }
.infographic-calloc .syn-comment { color: var(--syn-comment); }
.infographic-calloc .field-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.infographic-calloc .field-row label { font-size: 0.82rem; color: var(--ink-soft); }
.infographic-calloc .field-row input[type="number"] {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.86rem;
padding: 0.32rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
width: 3.6rem;
}
.infographic-calloc .field-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.infographic-calloc .ctrl-btn {
all: unset; cursor: pointer;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem; font-weight: 600;
padding: 0.42rem 0.9rem;
border-radius: 999px;
border: 1px solid var(--line);
background: var(--paper-alt);
color: var(--ink);
}
.infographic-calloc .ctrl-btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.infographic-calloc .ctrl-btn:hover { border-color: var(--accent); }
/* memory block visual */
.infographic-calloc .mem-label { font-family: 'IBM Plex Mono', monospace; font-size: 0.8rem; color: var(--ink-soft); margin-bottom: 0.4rem; }
.infographic-calloc .mem-row { display: flex; gap: 0.3rem; flex-wrap: wrap; margin-bottom: 0.4rem; }
.infographic-calloc .mem-cell {
width: 3.2rem;
height: 2.6rem;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid var(--line);
border-radius: 6px;
background: var(--paper-alt);
font-family: 'IBM Plex Mono', monospace;
font-size: 0.82rem;
font-weight: 700;
transition: border-color 0.25s, background 0.25s, opacity 0.25s, transform 0.25s;
}
.infographic-calloc .mem-cell.is-garbage { color: var(--warn); border-color: var(--warn); background: var(--warn-soft); font-style: italic; }
.infographic-calloc .mem-cell.is-zero { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.infographic-calloc .mem-cell.is-kept { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.infographic-calloc .mem-cell.is-new { color: var(--warn); border-color: var(--warn); background: var(--warn-soft); font-style: italic; }
.infographic-calloc .mem-cell.is-freed {
color: var(--ink-soft);
border-color: var(--line);
border-style: dashed;
background: repeating-linear-gradient(45deg, var(--paper-alt), var(--paper-alt) 5px, var(--line) 5px, var(--line) 6px);
opacity: 0.75;
cursor: not-allowed;
}
.infographic-calloc .warn-msg {
font-size: 0.8rem;
color: var(--warn);
font-weight: 600;
min-height: 1.2rem;
margin-bottom: 0.4rem;
}
.infographic-calloc .mem-cell input {
all: unset;
width: 100%;
text-align: center;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.82rem;
font-weight: 700;
color: inherit;
}
.infographic-calloc .mem-cell.enter { animation: calloc-pop 0.35s ease; }
@keyframes calloc-pop { from { opacity: 0; transform: scale(0.7); } to { opacity: 1; transform: scale(1); } }
.infographic-calloc .facts { font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; color: var(--ink-soft); margin-bottom: 0.3rem; }
.infographic-calloc .facts strong { color: var(--ink); }
.infographic-calloc .panel { display: none; }
.infographic-calloc .panel.is-active { display: block; }
.infographic-calloc .takeaway { font-size: 0.82rem; color: var(--ink-soft); margin-top: 1.4rem; border-top: 1px solid var(--line); padding-top: 0.9rem; }
.infographic-calloc .takeaway strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-calloc * { transition: none !important; animation: none !important; }
}
</style>
<h1>๐ฆ malloc ยท calloc ยท realloc</h1>
<p class="subhead">Three ways to ask the heap for space โ watch what's actually in the boxes.</p>
<div class="chip-row" id="mem-tabs">
<button class="chip is-active" data-tab="malloc">malloc</button>
<button class="chip" data-tab="calloc">calloc</button>
<button class="chip" data-tab="realloc">realloc</button>
</div>
<!-- malloc -->
<div class="panel is-active" data-tab="malloc">
<div class="code-panel"><span class="code-line" id="ma-code"></span></div>
<div class="field-row">
<label>n</label><input type="number" id="ma-n" value="5" min="1" max="10">
<button class="ctrl-btn primary" id="ma-alloc">malloc()</button>
<button class="ctrl-btn" id="ma-free">free()</button>
</div>
<div class="mem-label">ptr =</div>
<div class="mem-row" id="ma-row"></div>
<p class="facts" id="ma-facts"></p>
<p class="warn-msg" id="ma-warn"></p>
</div>
<!-- calloc -->
<div class="panel" data-tab="calloc">
<div class="code-panel"><span class="code-line" id="ca-code"></span></div>
<div class="field-row">
<label>n</label><input type="number" id="ca-n" value="5" min="1" max="10">
<button class="ctrl-btn primary" id="ca-alloc">calloc()</button>
<button class="ctrl-btn" id="ca-free">free()</button>
</div>
<div class="mem-label">ptr =</div>
<div class="mem-row" id="ca-row"></div>
<p class="facts" id="ca-facts"></p>
<p class="warn-msg" id="ca-warn"></p>
</div>
<!-- realloc -->
<div class="panel" data-tab="realloc">
<div class="code-panel">
<span class="code-line" id="re-code1"></span>
<span class="code-line" id="re-code2"></span>
</div>
<div class="field-row">
<label>malloc n</label><input type="number" id="re-n1" value="5" min="1" max="10">
<button class="ctrl-btn primary" id="re-alloc">malloc()</button>
</div>
<div class="mem-label">ptr = <span style="font-weight:400; color:var(--ink-soft);">(type into the boxes to โuseโ the memory)</span></div>
<div class="mem-row" id="re-row"></div>
<p class="facts" id="re-facts"></p>
<div class="field-row" style="margin-top:0.8rem;">
<label>realloc n</label><input type="number" id="re-n2" value="10" min="1" max="14">
<button class="ctrl-btn primary" id="re-realloc" disabled>realloc()</button>
<button class="ctrl-btn" id="re-free">free()</button>
</div>
<p class="warn-msg" id="re-warn"></p>
</div>
<p class="takeaway"><strong>malloc</strong> leaves garbage behind. <strong>calloc</strong> zeroes everything first. <strong>realloc</strong> keeps what was already there and only the new space is garbage. <strong>free</strong> gives the memory back โ but <code style="font-family:'IBM Plex Mono',monospace;">ptr</code> still points at it, so touching it again (or freeing it twice) is undefined behavior.</p>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-calloc')
|| document.querySelector('.infographic-calloc');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function $(sel) { return wrapper.querySelector(sel); }
function randGarbage() { return Math.floor(Math.random() * 20000) - 10000; }
// ---- tabs ----
const tabs = wrapper.querySelectorAll('#mem-tabs .chip');
const panels = wrapper.querySelectorAll('.panel');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('is-active'));
tab.classList.add('is-active');
panels.forEach(p => p.classList.toggle('is-active', p.dataset.tab === tab.dataset.tab));
});
});
// ================= malloc =================
const maN = $('#ma-n'), maCode = $('#ma-code'), maRow = $('#ma-row'), maFacts = $('#ma-facts'), maWarn = $('#ma-warn');
let maFreed = false;
function renderMallocCode() {
const n = Math.max(1, Math.min(10, parseInt(maN.value, 10) || 1));
maN.value = n;
maCode.innerHTML = '<span class="syn-keyword">int*</span> ptr = (<span class="syn-keyword">int*</span>) <span class="syn-func">malloc</span>(' + n + ' * <span class="syn-func">sizeof</span>(<span class="syn-keyword">int</span>));';
}
function maCellClick() {
if (maFreed) maWarn.textContent = '๐ซ Use-after-free โ ptr still points here, but this memory isn\u2019t yours anymore.';
}
function doMalloc() {
const n = Math.max(1, Math.min(10, parseInt(maN.value, 10) || 1));
maFreed = false;
maWarn.textContent = '';
maRow.innerHTML = '';
for (let i = 0; i < n; i++) {
const cell = document.createElement('div');
cell.className = 'mem-cell is-garbage enter';
cell.textContent = randGarbage();
cell.addEventListener('click', maCellClick);
maRow.appendChild(cell);
}
maFacts.innerHTML = n + ' ร 4 = <strong>' + (n * 4) + ' bytes</strong> allocated โ every box holds whatever was already in memory (garbage).';
}
function doMaFree() {
if (maRow.children.length === 0) { maWarn.textContent = 'Nothing allocated yet.'; return; }
if (maFreed) { maWarn.textContent = '๐ซ Double free โ this memory was already freed!'; return; }
maFreed = true;
maWarn.textContent = '';
Array.from(maRow.children).forEach(cell => cell.classList.add('is-freed'));
maFacts.innerHTML = 'Memory returned to the system โ <strong>ptr is now dangling</strong>.';
}
maN.addEventListener('input', renderMallocCode);
$('#ma-alloc').addEventListener('click', doMalloc);
$('#ma-free').addEventListener('click', doMaFree);
// ================= calloc =================
const caN = $('#ca-n'), caCode = $('#ca-code'), caRow = $('#ca-row'), caFacts = $('#ca-facts'), caWarn = $('#ca-warn');
let caFreed = false;
function renderCallocCode() {
const n = Math.max(1, Math.min(10, parseInt(caN.value, 10) || 1));
caN.value = n;
caCode.innerHTML = '<span class="syn-keyword">int*</span> ptr = (<span class="syn-keyword">int*</span>) <span class="syn-func">calloc</span>(' + n + ', <span class="syn-func">sizeof</span>(<span class="syn-keyword">int</span>));';
}
function caCellClick() {
if (caFreed) caWarn.textContent = '๐ซ Use-after-free โ ptr still points here, but this memory isn\u2019t yours anymore.';
}
function doCalloc() {
const n = Math.max(1, Math.min(10, parseInt(caN.value, 10) || 1));
caFreed = false;
caWarn.textContent = '';
caRow.innerHTML = '';
for (let i = 0; i < n; i++) {
const cell = document.createElement('div');
cell.className = 'mem-cell is-zero enter';
cell.textContent = '0';
cell.addEventListener('click', caCellClick);
caRow.appendChild(cell);
}
caFacts.innerHTML = n + ' ร 4 = <strong>' + (n * 4) + ' bytes</strong> allocated โ every box is zeroed out for you.';
}
function doCaFree() {
if (caRow.children.length === 0) { caWarn.textContent = 'Nothing allocated yet.'; return; }
if (caFreed) { caWarn.textContent = '๐ซ Double free โ this memory was already freed!'; return; }
caFreed = true;
caWarn.textContent = '';
Array.from(caRow.children).forEach(cell => cell.classList.add('is-freed'));
caFacts.innerHTML = 'Memory returned to the system โ <strong>ptr is now dangling</strong>.';
}
caN.addEventListener('input', renderCallocCode);
$('#ca-alloc').addEventListener('click', doCalloc);
$('#ca-free').addEventListener('click', doCaFree);
// ================= realloc =================
const reN1 = $('#re-n1'), reN2 = $('#re-n2');
const reCode1 = $('#re-code1'), reCode2 = $('#re-code2');
const reRow = $('#re-row'), reFacts = $('#re-facts'), reWarn = $('#re-warn');
const reAllocBtn = $('#re-alloc'), reReallocBtn = $('#re-realloc'), reFreeBtn = $('#re-free');
let reValues = [];
let reAllocated = false;
let reFreed = false;
function renderReCode() {
const n1 = Math.max(1, Math.min(10, parseInt(reN1.value, 10) || 1));
const n2 = Math.max(1, Math.min(14, parseInt(reN2.value, 10) || 1));
reN1.value = n1; reN2.value = n2;
reCode1.innerHTML = '<span class="syn-keyword">int*</span> ptr = (<span class="syn-keyword">int*</span>) <span class="syn-func">malloc</span>(' + n1 + ' * <span class="syn-func">sizeof</span>(<span class="syn-keyword">int</span>));';
reCode2.innerHTML = 'ptr = <span class="syn-func">realloc</span>(ptr, ' + n2 + ' * <span class="syn-func">sizeof</span>(<span class="syn-keyword">int</span>)); <span class="syn-comment">// ' + (n1 * 4) + ' โ ' + (n2 * 4) + ' bytes</span>';
}
function reCellClick() {
if (reFreed) reWarn.textContent = '๐ซ Use-after-free โ ptr still points here, but this memory isn\u2019t yours anymore.';
}
function renderReRow() {
reRow.innerHTML = '';
reValues.forEach((v, i) => {
const cell = document.createElement('div');
cell.className = 'mem-cell is-kept';
const input = document.createElement('input');
input.type = 'text';
input.value = v;
input.addEventListener('input', () => { reValues[i] = input.value; });
input.addEventListener('click', reCellClick);
cell.appendChild(input);
reRow.appendChild(cell);
});
}
function doMallocFirst() {
const n1 = Math.max(1, Math.min(10, parseInt(reN1.value, 10) || 1));
reValues = [];
for (let i = 0; i < n1; i++) reValues.push(randGarbage());
reAllocated = true;
reFreed = false;
reWarn.textContent = '';
renderReRow();
reFacts.innerHTML = n1 + ' ร 4 = <strong>' + (n1 * 4) + ' bytes</strong> allocated.';
reReallocBtn.disabled = false;
}
function doRealloc() {
if (!reAllocated) return;
if (reFreed) { reWarn.textContent = '๐ซ realloc() on freed memory โ undefined behavior.'; return; }
const n1 = reValues.length;
const n2 = Math.max(1, Math.min(14, parseInt(reN2.value, 10) || 1));
if (n2 > n1) {
for (let i = n1; i < n2; i++) reValues.push(randGarbage());
} else if (n2 < n1) {
reValues = reValues.slice(0, n2);
}
renderReCode();
reRow.innerHTML = '';
reValues.forEach((v, i) => {
const cell = document.createElement('div');
cell.className = 'mem-cell ' + (i < n1 && i < n2 ? 'is-kept' : 'is-new') + (i >= n1 ? ' enter' : '');
const input = document.createElement('input');
input.type = 'text';
input.value = v;
input.addEventListener('input', () => { reValues[i] = input.value; });
input.addEventListener('click', reCellClick);
cell.appendChild(input);
reRow.appendChild(cell);
});
reFacts.innerHTML = n1 + ' ร 4 โ ' + n2 + ' ร 4 = <strong>' + (n2 * 4) + ' bytes</strong> now. ' +
(n2 > n1 ? 'Original values kept, new boxes are garbage.' : (n2 < n1 ? 'Extra values were dropped.' : 'Same size โ nothing changed.'));
}
function doReFree() {
if (!reAllocated) { reWarn.textContent = 'Nothing allocated yet.'; return; }
if (reFreed) { reWarn.textContent = '๐ซ Double free โ this memory was already freed!'; return; }
reFreed = true;
reWarn.textContent = '';
Array.from(reRow.children).forEach(cell => {
cell.classList.add('is-freed');
const input = cell.querySelector('input');
if (input) input.readOnly = true;
});
reReallocBtn.disabled = true;
reFacts.innerHTML = 'Memory returned to the system โ <strong>ptr is now dangling</strong>.';
}
reN1.addEventListener('input', renderReCode);
reN2.addEventListener('input', renderReCode);
reAllocBtn.addEventListener('click', doMallocFirst);
reReallocBtn.addEventListener('click', doRealloc);
reFreeBtn.addEventListener('click', doReFree);
// ---- init ----
renderMallocCode();
doMalloc();
renderCallocCode();
doCalloc();
renderReCode();
})();
</script>๐ก Memory Layout in C (Stack vs Heap)
<div class="infographic-cmemlayout">
<style>
.infographic-cmemlayout {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--warn: #b45309;
--warn-soft: #fdf0dc;
--heap-color: #2563eb;
--stack-color: #a0509a;
}
.infographic-cmemlayout[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--warn: #e0a458;
--warn-soft: #3a2c14;
--heap-color: #5b8def;
--stack-color: #cf8fc9;
}
.infographic-cmemlayout {
box-sizing: border-box;
max-width: 420px;
margin: 0 auto;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', -apple-system, sans-serif;
padding: 0 clamp(1rem, 4vw, 2.25rem) 1.25rem;
}
.infographic-cmemlayout *, .infographic-cmemlayout *::before, .infographic-cmemlayout *::after {
box-sizing: border-box;
}
.infographic-cmemlayout h1 {
font-family: 'Fraunces', Georgia, serif;
font-weight: 600;
font-size: clamp(1.3rem, 3.5vw, 1.7rem);
margin: 1.25rem 0 0.2rem;
text-align: center;
}
.infographic-cmemlayout .subhead { color: var(--ink-soft); font-size: 0.85rem; margin-bottom: 1.3rem; text-align: center; }
.infographic-cmemlayout .mem-bar {
width: 11rem;
margin: 0 auto;
border: 2px solid var(--ink);
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.infographic-cmemlayout .seg {
display: flex;
align-items: center;
justify-content: center;
font-family: 'IBM Plex Mono', monospace;
font-weight: 700;
font-size: 0.8rem;
text-align: center;
border-bottom: 2px solid var(--ink);
}
.infographic-cmemlayout .seg:last-child { border-bottom: none; }
.infographic-cmemlayout .seg-code { height: 2.6rem; background: var(--paper-alt); }
.infographic-cmemlayout .seg-globals { height: 2.6rem; background: var(--paper-alt); font-size: 0.7rem; }
.infographic-cmemlayout .seg-flex {
height: 13rem;
display: flex;
flex-direction: column;
}
.infographic-cmemlayout .seg-heap {
background: var(--accent-soft);
color: var(--heap-color);
height: 0;
transition: height 0.35s ease;
overflow: hidden;
border-bottom: none;
}
.infographic-cmemlayout .seg-free {
background: var(--paper);
color: var(--ink-soft);
font-weight: 400;
font-size: 0.7rem;
flex: 1;
}
.infographic-cmemlayout .seg-stack {
background: #f4e9f3;
color: var(--stack-color);
height: 0;
transition: height 0.35s ease;
overflow: hidden;
border-bottom: none;
}
.infographic-cmemlayout[data-theme="dark"] .seg-stack { background: #2a1f2a; }
.infographic-cmemlayout .seg-flex.shake { animation: cmem-shake 0.4s ease; }
@keyframes cmem-shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-4px); }
75% { transform: translateX(4px); }
}
.infographic-cmemlayout .ctrl-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
margin-top: 1.1rem;
}
.infographic-cmemlayout .ctrl-btn {
all: unset; cursor: pointer;
text-align: center;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.78rem; font-weight: 600;
padding: 0.5rem 0.6rem;
border-radius: 8px;
border: 1px solid var(--line);
background: var(--paper-alt);
color: var(--ink);
}
.infographic-cmemlayout .ctrl-btn:hover { border-color: var(--accent); }
.infographic-cmemlayout .ctrl-btn.heap { border-color: var(--heap-color); color: var(--heap-color); }
.infographic-cmemlayout .ctrl-btn.stack { border-color: var(--stack-color); color: var(--stack-color); }
.infographic-cmemlayout .ctrl-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.infographic-cmemlayout .reset-row { margin-top: 0.5rem; text-align: center; }
.infographic-cmemlayout .reset-row .ctrl-btn { display: inline-block; }
.infographic-cmemlayout .crash-msg {
text-align: center;
font-size: 0.8rem;
color: var(--warn);
font-weight: 600;
min-height: 1.2rem;
margin-top: 0.6rem;
}
.infographic-cmemlayout .takeaway {
font-size: 0.82rem; color: var(--ink-soft);
margin-top: 1.3rem; border-top: 1px solid var(--line); padding-top: 0.9rem;
}
.infographic-cmemlayout .takeaway strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-cmemlayout * { transition: none !important; animation: none !important; }
}
</style>
<h1>๐บ๏ธ C Program Memory Layout</h1>
<p class="subhead">Heap and Stack grow toward each other.</p>
<div class="mem-bar">
<div class="seg seg-code">Code</div>
<div class="seg seg-globals">Global Variables</div>
<div class="seg seg-flex" id="seg-flex">
<div class="seg seg-heap" id="seg-heap"></div>
<div class="seg seg-free" id="seg-free">free space</div>
<div class="seg seg-stack" id="seg-stack"></div>
</div>
</div>
<div class="ctrl-grid">
<button class="ctrl-btn heap" id="heap-grow">malloc()</button>
<button class="ctrl-btn stack" id="stack-grow">call function()</button>
</div>
<div class="reset-row">
<button class="ctrl-btn" id="reset-btn">โฒ Reset</button>
</div>
<div class="crash-msg" id="crash-msg"></div>
<p class="takeaway"><strong>Grow either one too far</strong> and it runs straight into the other.</p>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-cmemlayout')
|| document.querySelector('.infographic-cmemlayout');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function $(sel) { return wrapper.querySelector(sel); }
const segFlex = $('#seg-flex');
const segHeap = $('#seg-heap');
const segFree = $('#seg-free');
const segStack = $('#seg-stack');
const crashMsg = $('#crash-msg');
const heapGrowBtn = $('#heap-grow');
const stackGrowBtn = $('#stack-grow');
const resetBtn = $('#reset-btn');
const TOTAL_UNITS = 8;
const UNIT_PX = 208 / TOTAL_UNITS; // seg-flex height is 13rem = 208px
let heapUnits = 0;
let stackUnits = 0;
function render() {
segHeap.style.height = (heapUnits * UNIT_PX) + 'px';
segStack.style.height = (stackUnits * UNIT_PX) + 'px';
segHeap.textContent = heapUnits > 0 ? 'Heap' : '';
segStack.textContent = stackUnits > 0 ? 'Stack' : '';
const freeUnits = TOTAL_UNITS - heapUnits - stackUnits;
segFree.textContent = freeUnits > 0 ? 'free space' : '';
heapGrowBtn.disabled = freeUnits <= 0;
stackGrowBtn.disabled = freeUnits <= 0;
}
function shake() {
segFlex.classList.remove('shake');
void segFlex.offsetWidth;
segFlex.classList.add('shake');
}
heapGrowBtn.addEventListener('click', () => {
const freeUnits = TOTAL_UNITS - heapUnits - stackUnits;
if (freeUnits <= 0) {
crashMsg.textContent = '๐ฅ Out of memory โ heap ran into the stack.';
shake();
return;
}
heapUnits++;
crashMsg.textContent = '';
render();
});
stackGrowBtn.addEventListener('click', () => {
const freeUnits = TOTAL_UNITS - heapUnits - stackUnits;
if (freeUnits <= 0) {
crashMsg.textContent = '๐ฅ Stack overflow โ stack ran into the heap.';
shake();
return;
}
stackUnits++;
crashMsg.textContent = '';
render();
});
resetBtn.addEventListener('click', () => {
heapUnits = 0;
stackUnits = 0;
crashMsg.textContent = '';
render();
});
render();
})();
</script>Static memory (like
int arr[10]) goes on stackDynamic memory (like
malloc) is allocated on heap
โ ๏ธ Common Mistakes in DMA
Mistake | Why itโs bad |
|---|---|
Forgetting | Leads to memory leak |
Using memory after | Undefined behavior (dangling pointer) |
Not checking | Can crash on NULL |
Incorrect size calculation | May lead to buffer overflows |
๐ Best Practices
โ Always check if allocation was successful
โ
Use sizeof instead of hardcoding
โ
Always free() when done
โ
Set pointer to NULL after freeing
โ Avoid memory leaks by keeping track of all allocations
๐ Real-Life Applications
๐ฒ Dynamic Data Structures: Linked Lists, Trees, Graphs
๐ฆ Memory-efficient storage in large programs
๐ฎ Game development and resource loading
๐พ Operating systems and embedded systems