C程序中变量的内存分配方式
- 静态存储区:
存放全局变量和静态变量 - 栈:
存放函数参数值,局部变量值等
在执行函数调用时,系统在栈上为函数内的局部变量及形参分配内存;函数执行结束时,自动释放内存
特点:先进后出,栈底是高地址段(向下生长) - 堆
动态内存从堆中分配函数所申请的内存,生存期由程序员自己决定
特点:从低地址端开始分配内存(向上生长)
动态内存分配函数
-
void * malloc(unsigned int size);
返回所申请内存的首地址,申请失败返回NULL。
使用:p = (int*)malloc(n*sizeof(int));//因为是返回任意类型,所以需要强制转换
注:
void f() ; // 无返回值 void* f(); // 返回一个任意类型指针 void (*f)(); // 声明一个指针,指向void x()类型函数 int * p1 = NULL //这是一个空指针,即无效指针 void * p2; //可指向任意类型
-
void * calloc(unsigned int num, unsigned int size);
向系统申请num个size大小的内存块,返回所申请内存的首地址,申请失败返回NULL。 -
void *realloc(void *p,unsigned int size);
改变原来分配(p指向)的存储空间的大小;
释放内存方法
- void free(void * p);
常见的内存错误及对策
-
内存分配未成功,却使用了它
注意找不到足够大的内存,就会分配失败;
解决方法:p = (int *)malloc(n*sizeof(int)); if(p == NULL){ printf("No enough memory!"); exit(1);//终止程序,exit(0)表示正常退出,exit(x)(x不为0)都表示异常退出 }
-
内存分配成功,但尚未初始化就引用它
解决方法:
使用memset()初始化;
指针变量只要初始化就赋值为NULL -
内存分配成功,且已初始化,但操作越界
解决方法:
计算动态分配内存字节数始终使用sizeof;
尽量使用strncpy(), fgets(), 等安全的函数。 -
释放了内存,却继续使用它(野指针,也称悬空指针)
①由于释放内存后,指针任然存在,只是指正指向的内存不能再被程序访问了。
②函数的return语句返回了不该返回的内存地址(比如函数内部的局部变量的地址,它在函数调用完毕后会被自动释放)
解决方法:
①尽量将free§集中在函数的入口处,然后立即将p=NULL;
②不要从函数返回局部变量的地址;使用二级指针;将返回值改成指针 -
给空指针指向的地方赋值
解决方法:
指针变量使用前一定要初始化。 -
没有释放内存,造成内存泄漏
-
重复释放同一块内存(会使程序异常中止)