简易内存池

提示:文章

文章目录

前言

前期疑问:

本文目标:


一、背景

二、题目

简易内存池

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

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字节内存,09地址内存连续空间不足20字节,往后查找到3049地址,返回首地址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

总结

未完待续

相关推荐
行云流水行云流水2 分钟前
数据库、数据仓库、数据中台、数据湖相关概念
数据库·数据仓库
John Song4 分钟前
Redis 集群批量删除key报错 CROSSSLOT Keys in request don‘t hash to the same slot
数据库·redis·哈希算法
写bug写bug9 分钟前
手把手教你使用JConsole
java·后端·程序员
异常君10 分钟前
Java 中 try-catch 的性能真相:全面分析与最佳实践
java·面试·代码规范
IvanCodes18 分钟前
七、Sqoop Job:简化与自动化数据迁移任务及免密执行
大数据·数据库·hadoop·sqoop
Clownseven26 分钟前
SSH/RDP无法远程连接?腾讯云CVM及通用服务器连接失败原因与超全排查指南
服务器·ssh·腾讯云
ricky_fan27 分钟前
window下配置ssh免密登录服务器
运维·服务器·ssh
tonexuan28 分钟前
MySQL 8.0 绿色版安装和配置过程
数据库·mysql
JohnYan36 分钟前
工作笔记- 记一次MySQL数据移植表空间错误排除
数据库·后端·mysql
程序员清风1 小时前
阿里二面:Kafka 消费者消费消息慢(10 多分钟),会对 Kafka 有什么影响?
java·后端·面试