简易内存池

提示:文章

文章目录

前言

前期疑问:

本文目标:


一、背景

二、题目

简易内存池

请实现一个简易内存池,根据请求命令完成内存分配和释放。请实现以下接口:

MemSystem(int space) - 系统初始化,内存池总大小为 space。

request(int size) - 请求分配指定大小内存,如果分配成功,返回分配到的内存首地址;如果内存不足,或指定的大小为0,则输出 -1

release(int addr) - 释放掉之前分配的内存,释放成功返回 true;如果释放不存在的首地址,则返回 false

注意:

1.内存池地址分配必须是连续内存,并优先从低地址分配。

2.内存释放后可被再次分配,已释放的内存在空闲时不能被二次释放。

3.不会释放已申请的内存块的中间地址。

4.释放操作只是针对首地址所对应的单个内存块进行操作,不会影响其它内存块。

输入

每行表示一个函数调用,初始化函数仅首行调用一次,累计函数调用不超过 100 次。

输出

答题时按照函数/方法原型中的要求(含返回值)进行实现,输出由框架完成(其中首行固定输出 null)

样例1

输入:

MemSystem(100)

request(10)

request(20)

release(0)

request(20)

request(10)

输出:

null

0

10

true

30

0

解释:

request(10):申请地址0~9的10个字节内存,返回首地址0

request(20):申请地址10~29的20字节内存,返回首地址10

release(0): 释放首地址为0的内存申请,0~9地址内存被释放,变为空闲,释放成功,无需输出

request(20):申请20字节内存,0~9地址内存连续空间不足20字节,往后查找到30~49地址,返回首地址30

request(10):申请10字节,0~9地址内存空间足够,返回首地址0

样例2

输入:

MemSystem(4)

request(3)

request(2)

release(3)

release(0)

request(2)

request(0)

输出:

null

0

-1

false

true

0

-1

解释:

题目代码框架

main.c文件

cpp 复制代码
#include <stdio.h>
#include "securec.h"
#include "solution.c"

// 以下为考题输入输出框架,此部分代码不建议改动;提交代码时请勿包含下面代码
static void SkipWs(void)
{
    char c = (char)getchar();
    while (c == ' ' || c == '\r' || c == '\n') {
        c = (char)getchar();
    }
    (void)ungetc(c, stdin);
}

static bool CallCreate(MemSystem **sys)
{
    int space = 0;
    bool isOk = false;

    do {
        SkipWs();
        char c = (char)getchar();
        if (c != '(') { break; }
        if (scanf_s("%d", &space) != 1) { break; }
        SkipWs();
        c = (char)getchar();
        if (c != ')') { break; }
        isOk = true;
        *sys = MemSystemCreate(space);
    } while (false);

    printf("null\n");
    return isOk;
}

static bool CallRequest(MemSystem *sys)
{
    int size = 0;
    int returnValue = 0;
    bool isOk = false;

    do {
        SkipWs();
        char c = (char)getchar();
        if (c != '(') { break; }
        if (scanf_s("%d", &size) != 1) { break; }
        SkipWs();
        c = (char)getchar();
        if (c != ')') { break; }
        isOk = true;
        returnValue = MemSystemRequest(sys, size);
        printf("%d", returnValue);
    } while (false);

    printf("\n");
    return isOk;
}

static bool CallRelease(MemSystem *sys)
{
    int addr = 0;
    bool returnValue = false;
    bool isOk = false;

    do {
        SkipWs();
        char c = (char)getchar();
        if (c != '(') { break; }
        if (scanf_s("%d", &addr) != 1) { break; }
        SkipWs();
        c = (char)getchar();
        if (c != ')') { break; }
        isOk = true;
        returnValue = MemSystemRelease(sys, addr);
        printf("%s", returnValue ? "true" : "false");
    } while (false);

    printf("\n");
    return isOk;
}

static bool GetCmdName(char* buffer, size_t size)
{
    SkipWs();
    size_t pos = 0;
    char c = (char)getchar();
    while (c != '\r' && c != '\n' && c != ' ' && c != '(' && feof(stdin) == 0 && pos < size) {
        buffer[pos++] = c;
        c = (char)getchar();
    }
    if (pos >= size) { return false; }
    buffer[pos] = '\0';
    if (pos == 0) { return feof(stdin) != 0; }
    if (feof(stdin) == 0) { (void)ungetc(c, stdin); }

    return true;
}

int main(void)
{
    char cmd[64] = {0};
    bool isOk = GetCmdName(cmd, sizeof(cmd));
    MemSystem *sys = NULL;
    if (strcmp(cmd, "MemSystem") != 0) { isOk = false; }
    if (isOk) { isOk = CallCreate(&sys); }

    while (isOk) {
        const char *cmds[] = {"request", "release"};
        bool (*funcs[])(MemSystem *sys) = {CallRequest, CallRelease};
        if (!GetCmdName(cmd, sizeof(cmd))) {
            isOk = false;
            break;
        }
        if (cmd[0] == '\0') {
            MemSystemFree(sys);
            return 0;
        }

        isOk = false;
        for (size_t i = 0; i < sizeof(cmds) / sizeof(cmds[0]); ++i) {
            if (strcmp(cmd, cmds[i]) == 0) {
                isOk = (*funcs[i])(sys);
                break;
            }
        }
    }

    printf("Error: Input format incorrect!");
    if (sys) { MemSystemFree(sys); }
    return 0;
}

solution.c文件

c 复制代码
#include <stdbool.h>

typedef struct {

} MemSystem;

// 注意:该函数为类构造函数,返回的对象指针将作为其他待实现函数的入参;框架代码在调用该函数后,会输出 null(而非指针)
static MemSystem *MemSystemCreate(int space)
{
    return NULL;
}

static int MemSystemRequest(MemSystem *sys, int size)
{
    return 0;
}

static bool MemSystemRelease(MemSystem *sys, int addr)
{
    return false;
}

static void MemSystemFree(MemSystem *sys)
{

}

三、解题

第一版代码

感觉这版代码就是东拼西凑的代码,竟然还通过了两个题目测试用例。

cpp 复制代码
#include <stdbool.h>
#include <stdio.h>
#include <malloc.h>
#include "securec.h"

typedef struct {
    int start;
    int end;
} MemoryUint;

typedef struct {
    bool status;
    int index;
} HashMap;

typedef struct {
    MemoryUint memoryUint[101];
    HashMap hashMap[101];
    int hashCount;
    int unitCount;
    int memLeftSize;
    int totalMemorySize;
} MemSystem;

static int compare(const void* a, const void* b)
{
    return ((HashMap*)a)->index - ((HashMap*)b)->index;
}

// 注意:该函数为类构造函数,返回的对象指针将作为其他待实现函数的入参;框架代码在调用该函数后,会输出 null(而非指针)
static MemSystem *MemSystemCreate(int space)
{
    MemSystem* sys = (MemSystem*)malloc(sizeof(MemSystem));
    if (sys == NULL) {
        return NULL;
    }
    memset_s(sys->memoryUint, sizeof(sys->memoryUint), 0, sizeof(sys->memoryUint));
    memset_s(sys->hashMap, sizeof(sys->hashMap), 0, sizeof(sys->hashMap));
    sys->totalMemorySize = space;
    sys->memLeftSize = space;
    sys->hashCount = 0;
    sys->unitCount = 0;
    return sys;
}

static int MemSystemRequest(MemSystem *sys, int size)
{
    if(size == 0)
    {
        return -1;
    }
    if(sys->hashCount == 0)
    {
        sys->memoryUint[0].start = 0;
        sys->memoryUint[0].end = sys->memoryUint[0].end + size;
        sys->hashMap[0].status = true;
        sys->hashMap[0].index = sys->memoryUint[0].start;
        sys->hashCount += 1;
        return sys->memoryUint[0].start;
    }

    for(int i = 0; i < sys->hashCount; i++)
    {
        if(sys->hashMap[i].status == true)
        {
            int spareMemSize = 0;
            if(sys->hashCount == 1)
            {
                if(sys->memoryUint[sys->hashMap[0].index].start > size)
                {
                    sys->memoryUint[0].start = 0;
                    sys->memoryUint[0].end = sys->memoryUint[0].start + size;

                    sys->hashMap[sys->hashCount].status = true;
                    sys->hashMap[sys->hashCount].index = sys->memoryUint[0].start;
                    sys->hashCount += 1;
                    qsort(sys->hashMap, sys->hashCount, sizeof(HashMap), compare);

                    return sys->memoryUint[0].start;
                }
                spareMemSize = sys->totalMemorySize - sys->memoryUint[sys->hashMap[0].index].end;
            }
            else
            {
                if(sys->memoryUint[sys->hashMap[0].index].start >= size)
                {
                    sys->memoryUint[0].start = 0;
                    sys->memoryUint[0].end = sys->memoryUint[0].start + size;

                    sys->hashMap[sys->hashCount].status = true;
                    sys->hashMap[sys->hashCount].index = sys->memoryUint[0].start;
                    sys->hashCount += 1;
                    qsort(sys->hashMap, sys->hashCount, sizeof(HashMap), compare);

                    return sys->memoryUint[0].start;
                }
                int lastMemInfo = 0;
                if(sys->hashMap[i + 1].status == false)
                {
                    lastMemInfo = sys->totalMemorySize;
                } else
                {
                    lastMemInfo = sys->hashMap[i + 1].index;
                }
                spareMemSize = lastMemInfo - sys->memoryUint[sys->hashMap[i].index].end;
            }

            if(spareMemSize >= size)
            {
                sys->memoryUint[sys->memoryUint[sys->hashMap[i].index].end].start = sys->memoryUint[sys->hashMap[i].index].end;
                sys->memoryUint[sys->memoryUint[sys->hashMap[i].index].end].end = sys->memoryUint[sys->memoryUint[sys->hashMap[i].index].end].start + size;
                sys->hashMap[sys->hashCount].status = true;
                sys->hashMap[sys->hashCount].index = sys->memoryUint[sys->memoryUint[sys->hashMap[i].index].end].start;
                sys->hashCount += 1;
                return sys->memoryUint[sys->memoryUint[sys->hashMap[i].index].end].start;
            }
        }
    }
    return -1;
}

static bool MemSystemRelease(MemSystem *sys, int addr)
{
    for(int i = 0; i < sys->hashCount; i++)
    {
        if(sys->hashMap[i].status == true)
        {
            if(sys->memoryUint[sys->hashMap[i].index].start == addr)
            {
                sys->hashMap[i].status = false;
                sys->hashMap[i].index = 0;
                for(int j = i; j < sys->hashCount; j++)
                {
                    bool status = sys->hashMap[j + 1].status;
                    int index = sys->hashMap[j + 1].index;
                    sys->hashMap[j].status = status;
                    sys->hashMap[j].index = index;
                }
                sys->hashCount -= 1;
                return true;
            }
        }

    }
    return false;
}

static void MemSystemFree(MemSystem *sys)
{
    free(sys);
}

尝试全例执行代码,下面的用例没有通过。

用例1

shell 复制代码
输入:
MemSystem(100)
request(10)
request(20)
request(30)
request(40)
预期输出:
null
0
10
30
60

实际错误输出

shell 复制代码
null
0
10
30
-1

这个测试用例没有通过是因为

cpp 复制代码
if(spareMemSize > size)
//  需要改成
if(spareMemSize >= size)

修改后上述测试用例通过,但是下面的测试用例失败

shell 复制代码
输入:
MemSystem(100)
request(10)
request(20)
request(30)
request(40)
release(30)
request(10)
request(10)
request(10)
预期输出:
null
0
10
30
60
true
30
40
50

实际错误输出为

shell 复制代码
null
0
10
30
60
true
30
30
30

总结

未完待续

相关推荐
xmweisi5 分钟前
【华为】报文统计的技术NetStream
运维·服务器·网络·华为认证
我爱松子鱼10 分钟前
MySQL 单表访问方法详解
数据库·mysql
菜鸟蹦迪13 分钟前
八股文实战之JUC:ArrayList不安全性
java
2501_9032386513 分钟前
Spring MVC配置与自定义的深度解析
java·spring·mvc·个人开发
我们的五年23 分钟前
MySQL存储引擎:选择与应用
数据库·mysql
逻各斯24 分钟前
redis中的Lua脚本,redis的事务机制
java·redis·lua
计算机毕设指导626 分钟前
基于Springboot学生宿舍水电信息管理系统【附源码】
java·spring boot·后端·mysql·spring·tomcat·maven
计算机-秋大田33 分钟前
基于Spring Boot的兴顺物流管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
计算机小白一个44 分钟前
蓝桥杯 Java B 组之背包问题、最长递增子序列(LIS)
java·数据结构·蓝桥杯
DC_BLOG1 小时前
Linux-GlusterFS进阶分布式卷
linux·运维·服务器·分布式