Title Image

Blog Logo

🌱 C/C++ Memory Layout

🌱 C/C++ Memory Layout

Memory layout là một khái niệm quan trọng trong ngôn ngữ lập trình C/C++. Nó liên quan đến cách các biến và đối tượng được tổ chức và lưu trữ trong bộ nhớ. Trong bài viết này, chúng ta sẽ tìm hiểu về memory layout và tầm quan trọng của nó trong lập trình C/C++.

    👉 Kiến trúc memory layout

    Trong C/C++, bộ nhớ được chia thành các vùng khác nhau, bao gồm:

  • vùng dữ liệu (data segment), chứa các biến toàn cục và static.
  • vùng stack (stack segment), lưu trữ các biến cục bộ và thông tin trong quá trình Function Call.
  • vùng heap (heap segment), sử dụng để cấp phát và giải phóng bộ nhớ động.
  • vùng code (text segment), chứa các câu lệnh để thực thi chương trình.

cpp memory layout
Memory Layout của một chương trình C/C++

    👉 Text Segment

    Dễ thấy theo hình trên, Text Segment là vùng nhớ thấp nhất trong các vùng (mặc định với Linker trên máy tính), nó sẽ lưu trữ các câu lệnh trong chương trình, và các giá trị constant, ví dụ các chuỗi.

    👉 Data Segment

    Data Segment là vùng nhớ để lưu trữ dữ liệu cố định, bao gồm biến toàn cục - Global và biến static. Đối với linker trên máy tính và các chương trình MCU thông thường, vùng Data Segment sẽ chia là 2 vùng nhỏ hơn:

  • Initialized Data Segment - Lưu trữ các biến global/static đã được khởi tạo giá trị.
  • Un-Initialized Data Segment (hay bss segment) - lưu trữ các biến global/static chưa được khởi tạo giá trị - Các chương trình thông thường sẽ set vùng nhớ bss segment với giá trị là 0 trong quá trình startup, trước khi gọi hàm main().

int global = 100;    // init data segment
int s_global;        // bss segment, value = 0
int bss_global;      // bss segment, value = 0

int main()
{
    static int number = 10;    // init data segment
}

    👉 Heap Segment

    Bộ nhớ trong vùng heap nằm ngoài phạm vi của các hàm và tồn tại đến khi chúng được giải phóng bằng cách sử dụng toán tử delete.

    Bộ nhớ Heap dùng cho khái niệm cấp phát động - dynamic memory allocation.

    👉 Stack Segment

    Các biến được khai báo trong một hàm (biến local) sẽ được lưu trữ trong vùng stack. Khi hàm kết thúc, các biến trong stack sẽ được tự động giải phóng. Điều này đảm bảo việc quản lý và giải phóng bộ nhớ tự động và tiết kiệm tài nguyên.

    Ngoài ra, Stack Segment còn được dùng để lưu trữ thông tin trong quá trình Function Call.

    Stack hoạt động dựa theo cơ chế LIFO (Last In - First Out), tức là thông tin được đẩy vào trước, sẽ được lấy ra sau, và ngược lại, giống như cách chúng ta để sách vào thùng, quyển sách cho vào đầu tiên, sẽ là quyển được lấy ra cuối cùng.

    ➤ Như hình trên, dễ thấy stack sẽ có chiều hướng đi xuống về mặt địa chỉ, nếu như chúng ta đẩy data vào, và loại stack được sử dụng thông dụng nhất (trong máy tính cũng như các dòng vi điều khiển), là stack loại Full Descending - tức là khi đẩy data vào thì các data sau sẽ có địa chỉ giảm dần, và địa chỉ ban đầu gọi là "địa chỉ đỉnh" của stack.

    Dưới đây là 4 loại stack trong thực tế mà mọi người có thể tham khảo thêm

cpp-stack-type
4 loại bộ nhớ stack trên thực tế

    👉 Tối ưu hóa memory layout

    Memory layout cũng có vai trò quan trọng trong việc tối ưu hóa hiệu suất chương trình. Tổ chức dữ liệu và sắp xếp biến trong bộ nhớ một cách tốt có thể làm giảm thời gian truy cập và tăng tốc độ thực thi chương trình.

    Trên đây là một số điểm cơ bản về memory layout trong C++. Hiểu rõ về cách các biến và đối tượng được tổ chức trong bộ nhớ giúp chúng ta phát triển chương trình hiệu quả và tránh các vấn đề liên quan đến quản lý bộ nhớ. Hi vọng bài viết này đã giúp bạn có cái nhìn tổng quan về memory layout trong lập trình C/C++.

>>>= Follow ngay =<<<

Để nhận được những bài học miễn phí mới nhất nhé 😊

Chúc các bạn học tập tốt 😊

                                        

Đăng nhận xét

0 Nhận xét