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; }