热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于结构体数组实现静态内存池管理

注:这篇博客主要讲了我用C语言实现静态内存池管理的算法和思想。首先建立这些内存块的结构体索引。然后用malloc申请我们需要管理的内存块。在申请好的内存池里,进行内存使用。申请用户需要的内存,用的是轮

注:这篇博客主要讲了我用C语言实现静态内存池管理的算法和思想。首先建立这些内存块的结构体索引。

然后用malloc申请我们需要管理的内存块。在申请好的内存池里,进行内存使用。申请用户需要的内存,

用的是轮询的方式,根据内存块的大小在几种不同的内存块中依次查找剩余空间。释放内存就是改变每块

内存的free size。在程序结束后,free全部的内存,销毁内存池。功能实现的手段比较原始,后期可以进行

改进。欢迎大家参考和指导。


静态内存池管理要求:

32字节的内存块数量100块

64字节的内存块数量100块
256字节的内存块数量50块
1024字节的内存块数量10块
4096字节的内存块数量3块

实现要求(给出函数原型,请大家实现函数体):
内存池初始化函数:int initMem(void),返回0成功,其他值失败
内存块申请函数:void *getMem(unsigned int size),成功返回内存块地址,失败返回NULL
内存块释放函数:int retMem(void *buf),返回0成功,其他值失败
内存池统计函数:void showMem(void),各内存当前申请数、释放数、成功失败情况统计,用printf输出显示即可

验证用测试用例(最低要求):
1、把32字节的内存块全部申请完->接着归还一块->再申请一块->全部释放完。要求showMem显示结果正确!
2、4096字节内存块全部申请再全部释放
3、5000字节内存块申请

4、所有提供的内存(各种大小)全部申请完,再全部释放完

5、申请一块32字节,对该内存块释放两次

memory_pool.h

#ifndef __MEMORY_POLL_H__
#define __MEMORY_POLL_H__

//定义内存池
struct Mem_Pool {

struct Mem_Chunk *MemChunk32;

struct Mem_Chunk *MemChunk64;

struct Mem_Chunk *MemChunk256;

struct Mem_Chunk *MemChunk1024;

struct Mem_Chunk *MemChunk4096;

};


//定义内存块
struct Mem_Chunk {

int num;

int size;

struct p_Mem_Block *pMemBlock;

}MemChunk32, MemChunk64, MemChunk256, MemChunk1024, MemChunk4096;

struct p_Mem_Block {

char *addr;

int request_num;

int free_num;

int free_size;

}pMemBlock32[100], pMemBlock64[100], pMemBlock256[50], pMemBlock1024[10], pMemBlock4096[3];


extern int initMem(void);
extern void *getMem(unsigned int size);
extern int retMem(void *buf);
extern void showMem(void);
extern int freeMem(void);

#endif


memory_pool.c

#include
#include
#include
#include "memory_pool.h"

//初始化内存块的大小、数量
struct Mem_Chunk MemChunk32 = {100, 32, NULL};
struct Mem_Chunk MemChunk64 = {100, 64, NULL};
struct Mem_Chunk MemChunk256 = {50, 256, NULL};
struct Mem_Chunk MemChunk1024 = {10, 1024, NULL};
struct Mem_Chunk MemChunk4096 = {3, 4096, NULL};

struct Mem_Pool MemPool = {&MemChunk32, &MemChunk64, &MemChunk256, &MemChunk1024, &MemChunk4096};

//用malloc申请内存,并将地址赋给定义的内存块结构体变量
int initMem(void)
{

int i;

for(i = 0; i

{

pMemBlock32[i].addr = (char*)malloc(MemChunk32.size);

if(NULL == pMemBlock32[i].addr) return -1;

pMemBlock32[i].request_num = 0;

pMemBlock32[i].free_num = 0;

pMemBlock32[i].free_size = MemChunk32.size;

}

for(i = 0; i

{

pMemBlock64[i].addr = (char*)malloc(MemChunk64.size);

if(NULL == pMemBlock64[i].addr) return -1;

pMemBlock64[i].request_num = 0;

pMemBlock64[i].free_num = 0;

pMemBlock64[i].free_size = MemChunk64.size;

}

for(i = 0; i

{

pMemBlock256[i].addr = (char*)malloc(MemChunk256.size);

if(NULL == pMemBlock256[i].addr) return -1;

pMemBlock256[i].request_num = 0;

pMemBlock256[i].free_num = 0;

pMemBlock256[i].free_size = MemChunk256.size;

}

for(i = 0; i

{

pMemBlock1024[i].addr = (char*)malloc(MemChunk1024.size);

if(NULL == pMemBlock1024[i].addr) return -1;

pMemBlock1024[i].request_num = 0;

pMemBlock1024[i].free_num = 0;

pMemBlock1024[i].free_size = MemChunk1024.size;

}

for(i = 0; i

{

pMemBlock4096[i].addr = (char*)malloc(MemChunk4096.size);

if(NULL == pMemBlock4096[i].addr) return -1;

pMemBlock4096[i].request_num = 0;

pMemBlock4096[i].free_num = 0;

pMemBlock4096[i].free_size = MemChunk4096.size;

}

printf("Memory Initialize Successfully!\n");

return 0;

}


void *getMem(unsigned int size)
{

int i, free_size;

char *pBlock;

if(size > 4096) return NULL;

if(size > 1024)

{

for(i = 0; i

pBlock = (char *)pMemBlock4096[i].addr;

free_size = pMemBlock4096[i].free_size;

if(free_size >= size){

pBlock = pBlock + 4096 - free_size;

pMemBlock4096[i].free_size -=size;

pMemBlock4096[i].request_num++;

return pBlock;

}

}

return NULL;

}

if(size > 256)

{

for(i = 0; i

pBlock = (char *)pMemBlock1024[i].addr;

free_size = pMemBlock1024[i].free_size;

if(pMemBlock1024[i].free_size >= size){

pBlock = pBlock + 1024 - free_size;

pMemBlock1024[i].free_size -=size;

pMemBlock1024[i].request_num++;

return pBlock;

}

}

return NULL;

}

if(size > 64)

{

for(i = 0; i

pBlock = (char *)pMemBlock256[i].addr;

free_size = pMemBlock256[i].free_size;

if(pMemBlock256[i].free_size >= size){

pBlock = pBlock + 256 - free_size;

pMemBlock256[i].free_size -=size;

pMemBlock256[i].request_num++;

return pBlock;

}

}

return NULL;

}

if(size > 32)

{

for(i = 0; i

pBlock = (char *)pMemBlock64[i].addr;

free_size = pMemBlock64[i].free_size;

if(pMemBlock64[i].free_size >= size){

pBlock = pBlock + 64 - free_size;

pMemBlock64[i].free_size -=size;

pMemBlock64[i].request_num++;

return pBlock;

}

}

return NULL;

}

if(size > 0)

{

for(i = 0; i

pBlock = (char *)pMemBlock32[i].addr;

free_size = pMemBlock32[i].free_size;

if(pMemBlock32[i].free_size >= size){

pBlock = pBlock + 32 - free_size;

pMemBlock32[i].free_size -=size;

pMemBlock32[i].request_num++;

return pBlock;

}

}

return NULL;

}

return NULL;

}


int retMem(void *buf)
{

int i, size;

char *pBlock;

char *pBuf = buf;

for(i = 0; i

pBlock = pMemBlock4096[i].addr;

if(pBuf >= pBlock && pBuf <= pBlock + 4096){

pMemBlock4096[i].free_size = pBlock + 4096 - pBuf;

pMemBlock4096[i].free_num++;

return 0;

}

}

for(i = 0; i

pBlock = pMemBlock1024[i].addr;

if(pBuf >= pBlock && pBuf <= pBlock + 1024){

pMemBlock1024[i].free_size = pBlock + 1024 - pBuf;

pMemBlock1024[i].free_num++;

return 0;

}

}

for(i = 0; i


pBlock = pMemBlock256[i].addr;

if(pBuf >= pBlock && pBuf <= pBlock + 256){

pMemBlock256[i].free_size = pBlock + 256 - pBuf;

pMemBlock256[i].free_num++;

return 0;

}


}


for(i = 0; i

pBlock = pMemBlock64[i].addr;

if(pBuf >= pBlock && pBuf <= pBlock + 64){

pMemBlock64[i].free_size = pBlock + 64 - pBuf;

pMemBlock64[i].free_num++;

return 0;

}

}

for(i = 0; i

pBlock = pMemBlock32[i].addr;

if(pBuf >= pBlock && pBuf <= pBlock + 32){

pMemBlock32[i].free_size = pBlock + 32 - pBuf;

pMemBlock32[i].free_num++;

return 0;

}

}

return -1;

}


void showMem(void)
{

int i, request_number, free_number;

for(i = 0; i

{

request_number = pMemBlock32[i].request_num;

free_number = pMemBlock32[i].free_num;

printf("The Memory_Chunk_32 pMemBlock32[%d]\n", i);

printf("request_number: %d     free_number: %d\n",request_number, free_number);

}



for(i = 0; i

{

request_number = pMemBlock64[i].request_num;

free_number = pMemBlock64[i].free_num;

printf("The Memory_Chunk_64 pMemBlock64[%d]\n", i);

printf("request_number: %d     free_number: %d\n",request_number, free_number);

}


for(i = 0; i

{

request_number = pMemBlock256[i].request_num;

free_number = pMemBlock256[i].free_num;

printf("The Memory_Chunk_256 pMemBlock256[%d]\n", i);

printf("request_number: %d     free_number: %d\n",request_number, free_number);

}


for(i = 0; i

{

request_number = pMemBlock1024[i].request_num;

free_number = pMemBlock1024[i].free_num;

printf("The Memory_Chunk_1024 pMemBlock1024[%d]\n", i);

printf("request_number: %d     free_number: %d\n",request_number, free_number);

}


for(i = 0; i

{

request_number = pMemBlock4096[i].request_num;

free_number = pMemBlock4096[i].free_num;

printf("The Memory_Chunk_4096 pMemBlock4096[%d]\n", i);

printf("request_number: %d     free_number: %d\n",request_number, free_number);

}

}

//销毁内存池,将申请的内存全部释放掉。
int freeMem(void)
{

int i;

for(i = 0; i

{

free(pMemBlock32[i].addr);

}

for(i = 0; i

{

free(pMemBlock64[i].addr);

}

for(i = 0; i

{

free(pMemBlock256[i].addr);

}

for(i = 0; i

{

free(pMemBlock1024[i].addr);

}

for(i = 0; i

{

free(pMemBlock4096[i].addr);

}

printf("Memory Freed Successfully!\n");

return 0;

}


main.c


#include
#include "memory_pool.h"


int test1(void)
{

int i, j;

char *pBlock[100];

for(i = 0; i <100; i++)

{

pBlock[i] = (char*)getMem(32);

if(pBlock[i] == NULL){

printf("Error: The request of Block[%d] failed!\n", i);

return -1;

}

}


if(retMem(pBlock[99]) == 0)

{

printf("The 100th Block is freed.\n");

}

else {

printf("Error: The 100th Block can't be freed!\n");

return -1;

}

pBlock[99] = (char*)getMem(32);

if(pBlock[99] == NULL){

printf("Error: The request of Block[99] failed!\n");

return -1;

}

for(i = 99; i >= 0; i--)

{

retMem(pBlock[i]);

}


showMem();

return 0;

}


int test2(void)
{

int i;

char *pBlock[3];

for(i = 0; i <3; i++)

{

pBlock[i] = (char*)getMem(4096);

if(pBlock[i] == NULL){

printf("Error: The request of Block[%d] failed!\n", i);

return -1;

}

}

for(i = 3; i >= 0; i--)

{

retMem(pBlock[i]);

}

showMem();

return 0;

}


int test3(void)
{

char *pBlock;

pBlock = (char*)getMem(5000);

if(pBlock == NULL){

printf("Error: The request of Block 5000 failed!\n");

return 0;

}

return -1;

}


int test4(void)
{

int i;

int j = 0;

char *pBlock[263];

for(i = 0; i <100; i++)

{

pBlock[j] = (char*)getMem(32);

if(pBlock[j] == NULL){

printf("Error: The request of Block32[%d] failed!\n", i);

return -1;

}

j++;

}

for(i = 0; i <100; i++)

{

pBlock[j] = (char*)getMem(64);

if(pBlock[j] == NULL){

printf("Error: The request of Block64[%d] failed!\n", i);

return -1;

}

j++;

}

for(i = 0; i <50; i++)

{

pBlock[j] = (char*)getMem(256);

if(pBlock[j] == NULL){

printf("Error: The request of Block256[%d] failed!\n", i);

return -1;

}

j++;

}

for(i = 0; i <10; i++)

{

pBlock[j] = (char*)getMem(1024);

if(pBlock[j] == NULL){

printf("Error: The request of Block1024[%d] failed!\n", i);

return -1;

}

j++;

}

for(i = 0; i <3; i++)

{

pBlock[j] = (char*)getMem(4096);

if(pBlock[j] == NULL){

printf("Error: The request of Block4096[%d] failed!\n", i);

return -1;

}

j++;

}

for(j = 262; j >= 0; j--)

{

retMem(pBlock[j]);

}

showMem();

return 0;

}


int test5(void)
{

char *pBlock;

pBlock = (char*)getMem(32);

if(pBlock == NULL){

printf("Error: The request of Block32 failed!\n");

return -1;

}

retMem(pBlock);

retMem(pBlock);

showMem();

return 0;

}


int main()
{

if(initMem() == -1)

{

printf("Error: Memory Pool Initialization Failed!\n");

return -1;

}

//test1();

//test2();

//test3();

//test4();

//test5();

freeMem();

return 0;

}


Makefile


objects = main.o memory_pool.o


main : $(objects)
cc -o main $(objects)


.PHONY : clean
clean :
-rm main $(objects)










推荐阅读
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • 在进行网络编程时,准确获取本地主机的IP地址是一项基本但重要的任务。Winsock作为20世纪90年代初由Microsoft与多家公司共同制定的Windows平台网络编程接口,为开发者提供了一套高效且易用的工具。通过Winsock,开发者可以轻松实现网络通信功能,并准确获取本地主机的IP地址,从而确保应用程序在网络环境中的稳定运行。此外,了解Winsock的工作原理及其API函数的使用方法,有助于提高开发效率和代码质量。 ... [详细]
  • 本文介绍了一种使用C语言实现三角形绘制的方法。通过在主函数中调用多个`printf`语句,分别输出不同数量的星号,从而构建出一个简单的直角三角形。该方法简单直观,适用于初学者理解和掌握基本的C语言输出操作。此外,还可以通过调整`printf`语句中的星号数量和行数,来绘制不同大小和形状的三角形。 ... [详细]
  • 在Ubuntu系统中,由于预装了MySQL,因此无需额外安装。通过命令行登录MySQL时,可使用 `mysql -u root -p` 命令,并按提示输入密码。常见问题包括:1. 错误 1045 (28000):访问被拒绝,这通常是由于用户名或密码错误导致。为确保顺利连接,建议检查MySQL服务是否已启动,并确认用户名和密码的正确性。此外,还可以通过配置文件调整权限设置,以增强安全性。 ... [详细]
  • C++ 进阶:类的内存布局与虚函数类的实现细节
    C++ 进阶:类的内存布局与虚函数类的实现细节 ... [详细]
  • 本文详细探讨了C语言中`extern`关键字的简易编译方法,并深入解析了预编译、`static`和`extern`的综合应用。通过具体的代码示例,介绍了如何在不同的文件之间共享变量和函数声明,以及这些关键字在编译过程中的作用和影响。文章还讨论了预编译过程中宏定义的使用,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • 本文介绍了C语言中指针的基础知识及其初步应用。首先,文章详细解释了如何定义变量和指针,例如通过 `int i, j, k;` 定义整型变量,以及使用 `int *pi, *pj, *pk;` 来声明指向整型数据的指针。接着,探讨了变量和指针的初始化方法,强调了正确的初始化对于避免程序错误的重要性。此外,还简要介绍了指针在数组、函数参数传递等场景中的基本应用,为初学者提供了全面的入门指导。 ... [详细]
  • C语言实现:深入解析希尔排序算法
    C语言实现:深入解析希尔排序算法 ... [详细]
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • 本文深入探讨了JVM的核心机制,重点解析了堆内存与栈内存的功能与特性。JVM栈主要负责程序的执行流程,包括方法调用和数据处理;而JVM堆则专注于数据的存储管理,主要用于存放对象实例。栈内存中存储的是基本数据类型以及堆中对象的引用,确保了程序在运行时能够高效地访问和操作数据。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • Dijkstra算法是一种高效的图论算法,用于在网络中寻找两点之间的最短路径。该算法通过逐步扩展已知最短路径的节点,最终确定从起点到终点的最优路径。在实际应用中,Dijkstra算法广泛应用于路由选择、交通规划等领域,能够有效解决大规模网络中的路径优化问题。 ... [详细]
  • 内网传送门【题目分析】在本次NOIP模拟赛中,题目主要考察了排列树与组合数学的综合应用,特别是拓扑排序的计算方法。题目的核心在于如何高效地求解树结构中的所有可能拓扑排序方案数,这对参赛者的算法设计和数学基础提出了较高要求。通过深入解析每个节点的排列组合关系,可以逐步构建出完整的解题思路。 ... [详细]
author-avatar
mobiledu2502891787
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有