C风格的动态内存管理(malloc、calloc、realloc、free)以及总结free崩溃常见的几种情况
程序员文章站
2022-05-12 09:17:50
...
申请内存
void * malloc(int size); //申请大小为size字节的队内存,失败返回NULL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void show(int* arr, int n) {
for (int i = 0; i < n; ++i) {
printf("arr[%d] = %d ",i,arr[i]);
}
printf("\n");
}
int main(){
int n = 10;
int* arr = (int*)malloc(n * sizeof(int));
show(arr,n);
if (arr != NULL) {
free(arr);
}
}
申请内存,并将内存初始化为0
void * calloc (int len,int size); //申请len*size大小的空间,并且将这块内存初始化为0
void show(int* arr, int n) {
for (int i = 0; i < n; ++i) {
printf("arr[%d] = %d ",i,arr[i]);
}
printf("\n");
}
int main(){
int n = 10;
int* brr = (int*)calloc(n,sizeof(int));
show(arr, n);
free(brr);
}
将已有的堆内存空间扩容至指定大小
void * realloc (void *memblock , size_t size);//memblock旧地址,size新地址的内存大小,而不是新增的大小
int main(){
int* crr = (int*)malloc(n * sizeof(int));
printf("crr = %x\n",crr);
crr = (int*)realloc(crr,90);
printf("crr = %x\n", crr);
}
释放内存
void free(void *memblock); //释放指定内存的堆空间
int main(){
int *p = (int*)malloc(100);
free(p);
}
free()如何知道需要释放多大的内存空间?
也就是说,比如我们用malloc向系统申请了100字节堆内存,实际上malloc会多申请几个字节,用来记录当前内存的大小以及前后的其他内存块的信息,具体实现有兴趣的读者可以去看ptmalloc的实现,这里不深入讲解。这就是我们调用free()没有传递内存大小但是它还是知道释放多大内存的原因。
总结几点free()不当造成的崩溃的问题:
- 重复释放,将已经释放不属于自己的内存又释放一次,造成崩溃:
int *p1 = (int*)malloc(100);
free(p1);
free(p1);
- 数组越界,导致内存块头部或者尾部信息被修改
int k = 10;
int* p = (int*)malloc(k*sizeof(int));
for (int i = 0; i <= k; ++i) {
p[i] = 0;
}
//最后一次循环将尾部信息的值改为0,释放时造成崩溃
free(p);
- 将堆内存的起始地址移动位置,如进行自增或者自减(++ --)
int k = 10;
int* p = (int*)malloc(k*sizeof(int));
for (int i = 0; i <= k; ++i) {
*p = 0;
p++;
}
//将堆内存起始地址修改,访问不到正确的堆头部或者尾部信息,导致内存释放出现问题
free(p);