简易内存池

提示:文章

文章目录

前言

前期疑问:

本文目标:


一、背景

二、题目

简易内存池

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

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

总结

未完待续

相关推荐
撸码到无法自拔8 分钟前
72 mysql 的客户端和服务器交互 returnGeneratedKeys
运维·服务器·数据库·mysql
zfj32110 分钟前
学英语学压测:01开源压测工具jmeter能干什么
java·jmeter·压力测试·负载·压测工具
ss27314 分钟前
被催更了,2025元旦源码继续免费送
java·vue.js·spring boot·后端·微信小程序·开源
Lugas17 分钟前
使用Vert.x实现反向代理
java·后端
JavaPub-rodert18 分钟前
项目48:简易语言学习助手【源代码】 --- 《跟着小王学Python·新手》
服务器·开发语言·python·学习·microsoft
孙尚香蕉31 分钟前
深入剖析MySQL数据库架构:核心组件、存储引擎与优化策略(二)
数据库·oracle
fengyehongWorld31 分钟前
Oracle 多租户架构简介
数据库·oracle
慢慢_飞38 分钟前
java.lang.Error: FFmpegKit failed to start on brand:
java·开发语言
码农君莫笑39 分钟前
SQL Server中最大并行度详解
服务器·数据库·sql·sqlserver
凡人的AI工具箱1 小时前
每天40分玩转Django:Django Celery
数据库·后端·python·django·sqlite