Bộ nhớ/Module 1 — Tổng kết & cheat sheet
6/13
Bài 6 / 13~12 phútMô hình bộ nhớ chương trìnhMiễn phí lượt xem

Module 1 — Tổng kết & cheat sheet

Recap mô hình bộ nhớ chương trình: địa chỉ, con trỏ, stack frame, heap, fragmentation, ba vùng nhớ. Cheat sheet một trang, glossary, pitfall và self-assessment.

TL;DR: Module 1 bóc tách cách một chương trình đang chạy bố trí bộ nhớ: mọi biến sống tại một địa chỉ, con trỏ/tham chiếu là biến lưu địa chỉ, stack chứa frame lời gọi (nhanh, tự dọn), heap chứa object động (linh hoạt, tốn kém, dễ fragment), và static chứa dữ liệu sống suốt đời chương trình. Đây là một trang để bookmark.

Đã đi qua những gì

Bạn bắt đầu từ khái niệm gốc — bộ nhớ là dãy ô đánh số, con trỏ là biến lưu số ô đó — rồi dùng nó để hiểu hai vùng nhớ đối lập. Stack cho biến cục bộ: mỗi lời gọi hàm push một frame, biến sống và chết theo frame, cực nhanh nhưng nhỏ và ngắn hạn. Heap cho dữ liệu động: cấp phát kích thước tuỳ ý lúc chạy, sống lâu hơn hàm, nhưng cần allocator và dễ bị fragmentation. Cuối cùng bạn đặt cả ba vùng (thêm static) cạnh nhau và rút ra quy tắc chọn vùng đúng cho từng dữ liệu — nền tảng để Module 2 nói về cache và Module 3 nói về bộ nhớ ảo.

mindmap
  root(("Mo hinh<br/>bo nho"))
    Dia chi
      O nho danh so theo byte
      Con tro = bien luu dia chi
      Tham chieu Java/Python
    Stack
      Frame moi loi goi ham
      Tu don theo LIFO
      Stack overflow khi de quy sau
    Heap
      Cap phat dong qua allocator
      Fragmentation
      Song lau hon ham
    Chon vung
      Nho ngan han to stack
      Lon song lau to heap
      Hang dung chung to static

🗺️ Cheat sheet

Khái niệmCốt lõiPitfall thường gặp
Địa chỉSố thứ tự của ô nhớ (từ 0)Nhầm địa chỉ với giá trị
Con trỏ / tham chiếuBiến lưu một địa chỉGán biến object = copy địa chỉ, không copy nội dung (aliasing)
Dereference (*p, obj.x)Đi tới địa chỉ để đọc/ghiDereference null → NullPointerException
Pass-by-value (Java)Copy giá trị; với object là copy referenceTưởng gán lại tham số đổi biến gốc
Stack frameTham số + biến cục bộ + return addrTrả về con trỏ tới biến cục bộ (C)
Stack overflowFrame chồng vượt giới hạn stackĐệ quy sâu phụ thuộc input
Heap allocatorDuyệt free list, cắt khốiCấp phát object tạm trong vòng lặp nóng
FragmentationTrống rải rác, không khối lớn liền"Còn bộ nhớ" mà vẫn OutOfMemory
GC compactionDời object sống, nén heap(C không làm được — fragment tích luỹ)
Static / globalCấp một lần, sống cả chương trìnhstatic mutable → race condition

📖 Glossary module

Thuật ngữĐịnh nghĩa 1 câu
Address (địa chỉ)Số thứ tự duy nhất của một ô nhớ trong RAM, bắt đầu từ 0
Pointer (con trỏ)Biến mà giá trị là một địa chỉ, "trỏ tới" ô nhớ khác
Reference (tham chiếu)Tên Java/Python cho con trỏ ẩn — biến object lưu địa chỉ object trên heap
DereferenceĐi tới địa chỉ một con trỏ lưu để đọc hoặc ghi giá trị ở đó
AliasingHai biến cùng trỏ tới một object → sửa qua biến này thấy ở biến kia
StackVùng nhớ LIFO chứa frame lời gọi hàm, tự dọn theo frame
Stack frameKhối nhớ một lời gọi hàm: tham số, biến cục bộ, địa chỉ trả về
Stack pointerThanh ghi theo dõi đỉnh stack; push/pop là dịch thanh ghi này
Stack overflowLỗi khi tổng frame vượt giới hạn stack (thường do đệ quy sâu)
HeapVùng nhớ lớn cho cấp phát động, vòng đời tuỳ ý
AllocatorBộ quản lý heap: tìm khối trống, cắt, đánh dấu, gộp khi free
Free listCấu trúc allocator dùng để theo dõi các khối nhớ trống
FragmentationBộ nhớ trống vỡ vụn (external) hoặc dư trong khối (internal)
CompactionGC dời object còn sống về sát nhau để dồn vùng trống
Static / BSS / DataVùng chứa biến toàn cục và hằng, sống suốt đời chương trình
Escape analysisPhân tích compiler: object không thoát khỏi hàm có thể đặt trên stack

⚠️ Pitfall tổng hợp

1. Gán biến object tưởng là copy:

List<String> backup = original;              // SAI: copy dia chi
List<String> backup = new ArrayList<>(original); // DUNG: copy noi dung

2. Gán lại tham số tưởng đổi biến gốc:

void f(String s) { s = s.toUpperCase(); }    // chi doi tham chieu cuc bo
void f(List<String> l) { l.add("x"); }       // sua noi dung -> thay o noi goi

3. Đệ quy sâu phụ thuộc input → tràn stack:

void traverse(Node n) { ...; traverse(n.next); }  // SAI voi list 100k phan tu
// DUNG: vong lap + ArrayDeque tren heap

4. Cấp phát object tạm trong vòng lặp nóng:

for (...) { StringBuilder sb = new StringBuilder(); ... } // SAI
StringBuilder sb = new StringBuilder();
for (...) { sb.setLength(0); ... }                        // DUNG: tai dung

5. Static mutable dùng chung giữa luồng:

static int count = 0; void inc() { count++; }    // SAI: race condition
private final AtomicInteger count = new AtomicInteger(); // an toan hon

✅ Self-assessment

Bạn đã đạt module này nếu trả lời được:

  • Explain được địa chỉ bộ nhớ và con trỏ là gì, vì sao mọi biến đều có địa chỉ — kể cả trong Java/Python.
    • Nếu chưa: đọc lại bài 01 mục 2–3.
  • Trace được cách stack frame được tạo và huỷ qua mỗi lời gọi hàm, và giải thích stack overflow.
    • Nếu chưa: đọc lại bài 02 mục 2–3.
  • Explain được heap, cấp phát động và vì sao fragmentation làm chậm hoặc cạn bộ nhớ.
    • Nếu chưa: đọc lại bài 03 mục 2–3.
  • Choose được vùng nhớ đúng (stack, heap, static) cho từng loại dữ liệu và giải thích trade-off.
    • Nếu chưa: đọc lại bài 04 mục 4.

🚀 What's next

Module 2 — Cache & memory hierarchy — trả lời câu hỏi tiếp theo: bạn đã biết dữ liệu sống ở đâu (stack/heap/static), nhưng truy cập nó nhanh chậm thế nào? Hoá ra RAM chậm hơn CPU hàng trăm lần, và cache là lớp đệm cứu vãn điều đó. Bạn sẽ học vì sao bố cục dữ liệu trong bộ nhớ (chứ không chỉ thuật toán) quyết định tốc độ, và cách viết code "thân thiện cache" nhanh gấp nhiều lần mà không đổi độ phức tạp big-O.

Bài tiếp theo: Module 2 — Cache & memory hierarchy: tổng quan

📚 Tài liệu mở rộng

  • Sách: Computer Systems: A Programmer's Perspective (Bryant & O'Hallaron) — chương 3 (machine-level representation) và 9 (virtual memory) là nền tảng vàng cho cả track.
  • Sách: The Garbage Collection Handbook (Jones, Hosking, Moss) — sâu về allocator và GC, cho ai muốn đào tận gốc heap.
  • Tài liệu: What Every Programmer Should Know About Memory (Ulrich Drepper) — kinh điển về bộ nhớ và cache, đọc dần qua Module 2.
  • Thực hành: chạy một chương trình C nhỏ với valgrind --tool=memcheck để thấy rò bộ nhớ và truy cập sai vùng — cảm nhận trực tiếp điều module này mô tả.

Bài này có giúp bạn hiểu bản chất không?

Hỏi đáp về bài này

Chưa có câu hỏi

Đặt câu hỏi

Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).

Đặt câu hỏi đầu tiên