zoukankan      html  css  js  c++  java
  • 内存管理基础

    C++中可以访问的内存,通常可以分为三类:静态常量区、调用栈和堆。通常编译器使用三块独立内存:一块用于静态变量(可能再细分),一块用于自动变量,另一块用于动态存储。

    静态变量区

    这一块内存用于静态变量。静态变量区是编译器在编译期间就已经确定好的数据。例如在全局范围内声明const char text[] = "Hello World!",字符串text就会被存放在静态变量区。

    特点

    1. 只读;
    2. 大小固定;
    3. 无法管理;
    4. 可以利用其特性在逻辑上做一些特定的优化。

    调用栈

    这一块内存用于自动变量。

    特点

    1. 被动分配,被动回收;
    2. 大小在运行时有一个动态调整的过程;
    3. 大小有系统限制;
    4. 底大顶小。

    问题

    1. 为什么变量有作用域?

    防止不同的变量使用相同的栈内存,导致后面的变量覆盖前面的数据,从而在使用前面的变量时输出后面的变量。所以设置作用域,使变量出了作用域不再有效。

    1. 为什么不建议使用递归?

    因为栈内存是一个非常珍贵的资源,而使用递归有时会产生死循环,将消耗栈内存,直至消耗完,从而产生StackOverflow的错误。

    注意

    1. 栈内存先进后出,轮流使用。

    同一块内存要在占用它的函数执行完毕,内存被回收之后,其它函数才能使用这一块内存。栈中的内存可以被轮流使用,这也是为什么正常的程序可以一直执行,而不会出现栈溢出的问题。

    1. 不要在函数体中声明大块内存(大型数组,大型结构体)。

    例如声明int arr[10240000],十分占用栈内存。栈内存十分珍贵,应避免这种情况。

    这一块变量用于动态存储。

    特点

    1. 堆大小较大;
    2. 主动分配,主动回收。

    分配

    分配方式 回收方式
    malloc/calloc free
    new delete
    new T[] delete[] T

    示例

    /* c 风格, 分配方式 1. */
    void * mem = malloc(1024);
    /* c 风格, 分配方式 2.*/
    void * mem = calloc(1024);
    /* C 风格, 回收内存. */
    free(mem);
    
    int * iptr = new int; // cpp new
    delete iptr;          // cpp delete
    
    int * iarrptr = new int[1024]; // cpp new T[]
    delete[] iarrptr;              // cpp delete[] T
    

    注意

    1. 不用堆内存时,一定要及时调用回收API回收内存。
    2. 访问申请的内存时不要超过申请的量,例如 int * ptr = new int[4]; ptr[8] = 0;否则会出现一系列未定义行为Undefined behavior。

    指针

    指针表示的时某块数据在内存中的地址,地址为整型,它能表示的范围因平台的不同而不同。

    程序类型 指针位数 等同于
    32位程序 32 uint32_t
    64位程序 64 uint64_t

    在同一平台上,任何一个指针都可以退化为整数表示,因为任何指针的本质都是一个整数,它代表着一个内存位置。

    基本操作

    1. 赋值
    2. 强制转换
    3. 解引用
    4. 加减
    int * ptr = new int;
    int * iptr = ptr;       // 1. 相同类型的指针直接赋值.
    char * c = (char *)ptr; // 2. 不同类型的指针需要强制转换.
    
    int i = *ptr; // 3. 解引用, 将内存 ptr 指向的内存中的内容赋值给变量 i.
    
    // 4. 加减. 指针的加减单位是以指针类型为依据的, int 在内存中占用 4 个字节, testPtr 加减每次的单位也是 4.
    // sizeof(int) == 4;
    int * arrPtr = new int[4];
    int * testPtr = arrPtr;
    printf("%u\n", testPtr); // 可将指针作为无符号整型输出.
    testPtr = testPtr + 1;
    printf("%u\n", testPtr);
    testPtr = testPtr + 1;
    printf("%u\n", testPtr);
    

    指针,指向指针的指针,指向指针的指针的指针

    视频链接

    1. (含字幕)C++ 让你不再害怕内存和指针 其一_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
    2. [(含字幕)C++ 让你不再害怕内存和指针 其二_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili](
  • 相关阅读:
    DBG
    gdb Debugging Full Example
    Java Warmup
    Dtrace for Linux 2016
    分布式系统理论进阶
    Java theory and practice
    Dealing with InterruptedException
    JVM 虚拟化
    Intro to Filtering with Network Monitor 3.0
    spring 官方文档
  • 原文地址:https://www.cnblogs.com/tianshihao/p/14082336.html
Copyright © 2011-2022 走看看