一、malloc和free函数介绍
在C语言中,malloc
和free
是用于动态内存管理的函数。
(1)malloc函数
malloc
函数用于在堆(heap)中分配指定大小的内存空间,并返回一个指向该内存块的指针。
原型如下:
cpp
void* malloc(size_t size);
size
参数表示要分配的内存块的大小,以字节为单位。- 函数返回一个指向分配内存块的指针,如果分配失败,则返回
NULL
。
使用场景:
- 动态分配内存,例如在程序运行时根据需要创建数据结构。
- 为字符串、数组、结构体等动态分配内存空间。
使用方法:
cpp
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ptr;
int num = 5;
// 动态分配内存
ptr = (int*)malloc(num * sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 使用指针访问和操作分配的内存
for (int i = 0; i < num; i++) {
ptr[i] = i + 1;
}
// 打印分配的内存
for (int i = 0; i < num; i++) {
printf("%d ", ptr[i]);
}
// 释放内存
free(ptr);
return 0;
}
(2)free函数
free
函数用于释放之前通过malloc
或calloc
函数动态分配的内存空间。
原型如下:
cpp
void free(void* ptr);
ptr
参数是一个指向先前分配的内存块的指针。如果ptr
为NULL
,则free
函数不执行任何操作。
使用场景:
- 释放通过
malloc
、calloc
或realloc
等函数动态分配的内存。 - 避免内存泄漏,即释放不再使用的内存,以便其他代码可以使用该内存。
使用方法:
cpp
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ptr = (int*)malloc(5 * sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 使用动态分配的内存
// 释放内存
free(ptr);
return 0;
}
一旦调用了free
函数,就应该避免继续使用已释放的内存,已释放的内存将不再属于程序的有效内存区域,并且可能被其他部分重用。在释放内存后继续使用已释放的内存会导致未定义的行为和潜在的错误。
二、实现自己的malloc和free函数
定义一个数组 unsigned char buff[1024*100]; 然后使用C语言代码写个my_malloc和my_free函数,对这个buff数组的空间进行管理。 用户调用my_malloc和my_free函数管理这段空间。
实现代码:
cpp
#include <stdio.h>
#include <stdlib.h>
#define BUFF_SIZE (1024 * 100)
unsigned char buff[BUFF_SIZE];
typedef struct {
unsigned char* start;
size_t size;
} MemoryBlock;
MemoryBlock memoryBlocks[BUFF_SIZE] = {0};
int numBlocks = 0;
void* my_malloc(size_t size) {
// 寻找空闲块
for (int i = 0; i < numBlocks; i++) {
if (memoryBlocks[i].size == 0 && size <= BUFF_SIZE) {
memoryBlocks[i].start = buff;
memoryBlocks[i].size = size;
return memoryBlocks[i].start;
}
}
// 分配新的块
if (numBlocks < BUFF_SIZE) {
memoryBlocks[numBlocks].start = buff + numBlocks;
memoryBlocks[numBlocks].size = size;
numBlocks++;
return memoryBlocks[numBlocks - 1].start;
}
// 分配失败
return NULL;
}
void my_free(void* ptr) {
// 查找要释放的块
for (int i = 0; i < numBlocks; i++) {
if (memoryBlocks[i].start == ptr) {
memoryBlocks[i].size = 0;
break;
}
}
}
int main() {
// 使用my_malloc和my_free进行内存管理
unsigned char* ptr1 = (unsigned char*)my_malloc(10);
unsigned char* ptr2 = (unsigned char*)my_malloc(20);
if (ptr1 != NULL && ptr2 != NULL) {
// 使用分配的内存
for (int i = 0; i < 10; i++) {
ptr1[i] = i;
}
for (int i = 0; i < 20; i++) {
ptr2[i] = i + 10;
}
// 打印分配的内存
printf("ptr1: ");
for (int i = 0; i < 10; i++) {
printf("%d ", ptr1[i]);
}
printf("\n");
printf("ptr2: ");
for (int i = 0; i < 20; i++) {
printf("%d ", ptr2[i]);
}
printf("\n");
}
my_free(ptr1);
my_free(ptr2);
return 0;
}
说明:
-
buff
数组是用于存储分配的内存块的总空间。 -
MemoryBlock
结构体用于记录每个内存块的起始位置和大小。 -
my_malloc
函数用于分配指定大小的内存块,在memoryBlocks
数组中找到一个空闲块或分配一个新块,并返回其起始地址。 -
my_free
函数用于释放先前分配的内存块,在memoryBlocks
数组中查找要释放的块,并将其大小设置为0。 -
在
main
函数中,通过调用my_malloc
来分配内存块,并通过调用my_free
来释放内存块。