• C的内存四大区


    前提

    看视频得来的内容,只知道不止4个区,但主要是这4个区。

    四区

    静态区
    用于存放所有的全局变量和静态变量。
    int a=10; //静态区 int main(){ static int b=20; //静态区 return 0; }
    代码区
    就是存放程序的执行代码,运行时该区内容不可修改。
    栈区
    用于存放所有的局部auto变量(非static,非register等),先进后出原则!
    需要说明的是,栈区通常比较小,以KB为单位!所以存在overstack的可能性!--也就是俗称的爆栈~
    int max(int &a, int &b){ //a、b均在栈区。C语言中函数的形参入栈顺序是从右往左! return a>b?a:b; } int main(){ int a=0;//栈区 }
    堆区
    空间较大,需要手动分配及释放,如果忘记释放,存在溢出可能。
    堆空间比较自由,没有进出的顺序。
    C语言中使用void *p = malloc(size)分配空间,使用free(p)释放空间。
    需要注意的是,分配后,空间会有残余内容,需要手动清理。
    
    int *p = (int*) malloc( sizeof(int) * 10 ); //分配了40个字节
    free(p); //释放了分配的空间。

    以上,面试的时候通常会问到什么时候会栈溢出,根据栈区的定义,只要局部变量的总长度超出栈长度即可。

    例如,

    int arr[1024*1024*1024]={0}; //栈空间,超长
    while(1){ int a=0; //栈空间,无限压入 }
    //或者,递归次数太多!

    注意,malloc分配的空间并未提供初始化,所以需要手动初始化。

    memset(p, initVal, len); //将p地址开始的len长度范围内的空间的值初始化为initVal。

    C中提供了另外两个函数来操作堆空间。

    void *calloc(size_t _NumOfElements, size_t _SizeOfElement); //需要提供元素类型的数量及长度
    
    void *realloc(void *p, size_t _NewSize); //重新分配空间。需要提供原空间地址以及新空间的长度。注意,如果原地址没有足够的连续空间,那会复制到新空间,并释放原空间。

    realloc会返回新的空间地址(或者和原地址相同),或者返回NULL(0)--如果堆中任何地方都没有足够的空间!

    另外,其超出原空间长度的部分,内容不会初始化。

    测试代码

    #include <memory.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    /**
     * @brief test_heap 验证C函数形参是从右往左压入栈中
     * @param a
     * @param b
     */
    void test_heap(int a, int b) {
        printf("first parameter's addr is [%d],
    second parameter's addr is [%d]
    ", &a, &b);
    }
    
    int main() {
        printf("sizeof(int) = %d
    ", sizeof(int));
    
        int *pi = (int *)malloc(sizeof(int) * 10); //手动分配堆内存
        for (int i = 0; i != 10; ++i) {            //注意,这里的10的单位是int!
            printf("pi[%d] = %d, addr = %d
    ", i, pi[i], &pi[i]);
        }
    
        //手动清零
        memset(pi, 0, 10 * sizeof(int)); //注意,这里的长度单位是字节
        for (int i = 0; i != 10; ++i) {  //注意,这里的10的单位是int!
            printf("pi[%d] = %d, addr = %d
    ", i, pi[i], &pi[i]);
        }
    
        free(pi);
    
        //
        pi = (int *)calloc(10, sizeof(int)); // calloc
        for (int i = 0; i != 10; ++i) {      //注意,这里的10的单位是int!
            printf("pi[%d] = %d, addr = %d
    ", i, pi[i], &pi[i]);
        }
        //    free(pi); //note this and realloc
    
        printf("after free, pi = %d
    ", pi);
        int *pi2 = (int *)realloc(pi, 80); // 20是比原来短了。注意,如果使用pi,则之前不能free(pi)。
        printf("after realloc, pi = %d
    ", pi);
        printf("after realloc, pi2 = %d
    ", pi2); //如果整个堆当中都没有任何一处的内存能够满足realloc的需求。则此次分配失败,返回值为NULL
        for (int i = 0; i != 20; ++i) { //注意,这里的10的单位是int!
            printf("pi[%d] = %d, addr = %d
    ", i, pi2[i], &pi2[i]);
        }
        free(pi2);
        free(pi); // free(pi2) is ok
    
        //
        test_heap(3, 5);
    
        return 0;
    }
  • 相关阅读:
    squid代理
    日志、远程日志、日志轮询、DHCP
    环境变量、进程
    rpm、yum
    filesystem安装后产生所有目录
    vRO 添加已有磁盘到VM
    python笔记-8(线程,进程,协程,io多路复用)
    python笔记-7(面向对象、类、面向对象进阶、异常处理、断言、反射、网络(套接字)编程、)
    python3 封装
    python3 继承
  • 原文地址:https://www.cnblogs.com/larryzeal/p/5618776.html
Copyright © 2020-2023  润新知