欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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()如何知道需要释放多大的内存空间?

C风格的动态内存管理(malloc、calloc、realloc、free)以及总结free崩溃常见的几种情况
也就是说,比如我们用malloc向系统申请了100字节堆内存,实际上malloc会多申请几个字节,用来记录当前内存的大小以及前后的其他内存块的信息,具体实现有兴趣的读者可以去看ptmalloc的实现,这里不深入讲解。这就是我们调用free()没有传递内存大小但是它还是知道释放多大内存的原因。

总结几点free()不当造成的崩溃的问题:

  1. 重复释放,将已经释放不属于自己的内存又释放一次,造成崩溃:
int *p1 = (int*)malloc(100);
free(p1);
free(p1);
  1. 数组越界,导致内存块头部或者尾部信息被修改
int k = 10;
int* p = (int*)malloc(k*sizeof(int));
for (int i = 0; i <= k; ++i) {
	p[i] = 0;
}
//最后一次循环将尾部信息的值改为0,释放时造成崩溃
free(p);
  1. 将堆内存的起始地址移动位置,如进行自增或者自减(++ --)
int k = 10;
int* p = (int*)malloc(k*sizeof(int));
for (int i = 0; i <= k; ++i) {
	*p = 0;
	p++;
}
//将堆内存起始地址修改,访问不到正确的堆头部或者尾部信息,导致内存释放出现问题
free(p);