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],\nsecond parameter's addr is [%d]\n", &a, &b);
}

int main() {
    printf("sizeof(int) = %d\n", sizeof(int));

    int *pi = (int *)malloc(sizeof(int) * 10); //手动分配堆内存
    for (int i = 0; i != 10; ++i) {            //注意,这里的10的单位是int!
        printf("pi[%d] = %d, addr = %d\n", 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\n", 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\n", i, pi[i], &pi[i]);
    }
    //    free(pi); //note this and realloc

    printf("after free, pi = %d\n", pi);
    int *pi2 = (int *)realloc(pi, 80); // 20是比原来短了。注意,如果使用pi,则之前不能free(pi)。
    printf("after realloc, pi = %d\n", pi);
    printf("after realloc, pi2 = %d\n", pi2); //如果整个堆当中都没有任何一处的内存能够满足realloc的需求。则此次分配失败,返回值为NULL
    for (int i = 0; i != 20; ++i) { //注意,这里的10的单位是int!
        printf("pi[%d] = %d, addr = %d\n", i, pi2[i], &pi2[i]);
    }
    free(pi2);
    free(pi); // free(pi2) is ok

    //
    test_heap(3, 5);

    return 0;
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值