程序的内存分配

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int global_data = 1;
static int global_static_data = 1;

int* stack_data()
{
int d = 2;
return &d;
}

int * heap_data()
{
int* e = new int(6); // 程序员手动申请内存,分配在堆区
return e;
}

int static_data()
{
static int sti = 1;
return sti;
}

int main() {
// int* stack_ptr = stack_data();
// cout << "局部变量(栈区)访问: " << *stack_ptr << endl; // 错误,因为栈区内存被释放了

int* heap_ptr = heap_data();
cout << "局部变量(堆区)访问: " << *heap_ptr << endl; // 正确

int static_local_data = static_data();
int local_data = 8;
cout << "static_local_data: " << (uintptr_t)&static_local_data << endl;
cout << "static_global_data: " <<(uintptr_t) &global_static_data << endl;
cout << "global_data: " << (uintptr_t)&global_data << endl;
cout << "local_data: " << (uintptr_t)&local_data << endl;
return 0;
}

局部变量(堆区)访问: 6
static_local_data: 140724477297976
static_global_data: 94198146936852
global_data: 94198146936848
local_data: 140724477297980

在C++中,内存通常被划分为几个不同的区域,每个区域都有其特定的用途。以下是C++中常见的内存区域及其特点:

  1. 栈区(Stack)
    特点
    ◦ 栈区用于存储局部变量、函数参数、函数调用的返回地址等。
    ◦ 内存分配和释放由编译器自动管理,遵循“后进先出”(LIFO)的原则。
    ◦ 栈区的内存分配速度快,但大小有限,通常较小(几MB)。
    ◦ 当函数调用结束时,栈上的局部变量会自动被销毁。
    示例

    void foo() {
    int x = 10; // x 分配在栈上
    } // x 在函数结束时自动销毁
  2. 堆区(Heap)
    特点
    ◦ 堆区用于动态内存分配,程序员可以手动控制内存的分配和释放。
    ◦ 堆区的内存分配速度较慢,但大小通常较大(受系统内存限制)。
    ◦ 内存的分配和释放需要通过 newdelete(或 mallocfree)来手动管理。
    ◦ 如果不手动释放内存,可能会导致内存泄漏。
    示例

    int* p = new int(10); // 在堆上分配一个整数
    delete p; // 手动释放内存
  3. 全局区(Global/Static Area)
    特点
    ◦ 全局区用于存储全局变量和静态变量(包括静态局部变量和静态类成员变量)。
    ◦ 全局变量和静态变量的生命周期贯穿整个程序的运行时间。
    ◦ 全局区在程序启动时分配内存,在程序结束时释放内存。
    ◦ 全局区通常分为两个部分:data 段(已初始化的全局/静态变量)和 bss 段(未初始化的全局/静态变量)。
    示例

    int globalVar = 10; // 全局变量,分配在全局区
    void foo() {
    static int staticVar = 20; // 静态局部变量,分配在全局区
    }
  4. 代码区(Text/Code Segment)
    特点
    ◦ 代码区用于存储程序的二进制代码(即编译后的机器指令)。
    ◦ 代码区通常是只读的,防止程序在运行时意外修改指令。
    ◦ 代码区的大小在编译时确定,且在程序运行期间不会改变。
    示例

    void bar() {
    // 函数的代码存储在代码区
    }
  5. 常量区(Constant Area)
    特点
    ◦ 常量区用于存储字符串常量和全局常量。
    ◦ 常量区通常是只读的,防止程序在运行时修改常量。
    ◦ 常量区的内存分配在程序启动时完成,在程序结束时释放。
    示例

    const char* str = "Hello, World!"; // 字符串常量存储在常量区

总结:
栈区:用于局部变量和函数调用,自动管理,速度快,大小有限。
堆区:用于动态内存分配,手动管理,速度慢,大小较大。
全局区:用于全局变量和静态变量,生命周期贯穿整个程序。
代码区:用于存储程序的二进制代码,只读。
常量区:用于存储字符串常量和全局常量,只读。