1. malloc 関数と free 関数の概要
C 言語では、malloc と free は動的メモリ管理に使用される関数です。
(1) malloc 関数
malloc 関数は、指定したサイズのメモリ空間をヒープ上に確保し、メモリブロックへのポインタを返します。
プロトタイプは次のとおりです。
void* malloc(size_t size);
size パラメータは、割り当てられるメモリ ブロックのサイズをバイト単位で示します。
この関数は、割り当てられたメモリ ブロックへのポインタを返します。割り当てが失敗した場合は NULL を返します。
使用するシーン:
プログラムの実行中に必要に応じてデータ構造を作成するなど、動的にメモリを割り当てます。
文字列、配列、構造体などにメモリ空間を動的に割り当てます。
説明書:
#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 関数によって動的に割り当てられたメモリ空間を解放するために使用されます。
プロトタイプは次のとおりです。
void free(void* ptr);
ptr パラメータは、以前に割り当てられたメモリ ブロックへのポインタです。ptr が NULL の場合、free 関数は何も行いません。
使用するシーン:
malloc、calloc、realloc などの関数を通じて、動的に割り当てられたメモリを解放します。
メモリ リークを回避します。つまり、使用されなくなったメモリを解放して、他のコードがそのメモリを使用できるようにします。
説明書:
#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関数を呼び出した場合、解放されたメモリはプログラムの有効なメモリ領域ではなくなり、他の部分で再利用される可能性があるため、解放されたメモリを使い続けることは避けるべきです。解放されたメモリを使用し続けると、未定義の動作や潜在的なバグが発生する可能性があります。
2. 独自の malloc 関数と free 関数を実装する
配列 unsigned char buff[1024*100]; を定義し、C 言語コードを使用して my_malloc 関数と my_free 関数を記述し、この buff 配列のスペースを管理します。ユーザーは、my_malloc 関数と my_free 関数を呼び出して、このスペースを管理します。
実装コード:
#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 を呼び出してメモリ ブロックを解放します。