C 实现池内存API-处理联合

C 实现池内存API-处理联合,c,memory,malloc,free,C,Memory,Malloc,Free,我想为一个数据结构实现一个API,它预先将内存分配给若干特定大小的对象,而不是每次根据需要为每个对象使用“malloc”和“free” API应包括以下三个功能: pool* API_init(size_t sizeOfObj, int numOfObj) 接受两个参数,对象大小和我们希望存储的此类对象的数量,并返回指向池的指针—一种管理内存的数据结构 void* API_malloc(Pool* pool) 接受池并返回单个对象的新分配指针 void API_free(Pool* pool

我想为一个数据结构实现一个API,它预先将内存分配给若干特定大小的对象,而不是每次根据需要为每个对象使用“malloc”和“free”

API应包括以下三个功能:

pool* API_init(size_t sizeOfObj, int numOfObj)
接受两个参数,对象大小和我们希望存储的此类对象的数量,并返回指向池的指针—一种管理内存的数据结构

void* API_malloc(Pool* pool)
接受池并返回单个对象的新分配指针

void API_free(Pool* pool, void* obj)
接受两个参数,池和需要标记为未使用的地址

方法“API_malloc”和“API_free”的复杂度时间要求为常数,池的内存复杂度应为“sizeOfObj”*“numOfObj”+常数

为了处理片段,我想将池定义为大小为'sizeOfObj'字节的块的链表,它还包含指向下一个未使用块的指针。 为了节省内存空间,我决定使用UNION定义块

这是我的实现:

#include <stdio.h>
#include <stdlib.h>

typedef struct Pool Pool;
typedef union Chunk Chunk;


union Chunk{

    char* padding;
    Chunk* next;
};

struct Pool{

    Chunk* nextFreeChunk;
};

Pool* API_init(int sizeOfObj, int numOfObj){

    Pool* res = (Pool*) malloc(sizeof(Pool));
    Chunk* next;
    Chunk* curr;

    for(int i = numOfObj -1; i >= 0; i--){

        curr = (Chunk*) malloc (sizeof(Chunk));
        curr->padding = (char*) malloc(sizeOfObj);

        if(i < numOfObj -1)
            curr->next = next;

        next = curr;
    }

    res->nextFreeChunk = curr;
    return res;
}

void* API_malloc(Pool* pool){

    void* res = pool->nextFreeChunk;
    pool->nextFreeChunk = (pool->nextFreeChunk)->next;
    return res;
}

void API_free(Pool* pool, void* obj){

    Chunk* ch = (Chunk*) obj;
    ch->next = pool->nextFreeChunk;
    pool->nextFreeChunk = ch;
}
#包括
#包括
类型定义结构池;
typedef联合块;
联合块{
字符*填充;
块*下一步;
};
结构池{
Chunk*nextFreeChunk;
};
池*API_init(int-sizeOfObj,int-numobj){
Pool*res=(Pool*)malloc(sizeof(Pool));
块*下一步;
块*curr;
对于(int i=numobj-1;i>=0;i--){
curr=(Chunk*)malloc(sizeof(Chunk));
curr->padding=(char*)malloc(sizeOfObj);
if(i下一步=下一步;
下一个=当前;
}
res->nextFreeChunk=curr;
返回res;
}
void*API_malloc(池*Pool){
void*res=pool->nextFreeChunk;
pool->nextFreeChunk=(pool->nextFreeChunk)->下一步;
返回res;
}
无效API_自由(池*池,无效*obj){
Chunk*ch=(Chunk*)obj;
ch->next=pool->nextFreeChunk;
pool->nextFreeChunk=ch;
}
我的问题是,正如我定义的,块的大小不一定是给定的‘sizeOfObj’,而且字符指针正在浪费内存(而不是常量)

我知道union不能将灵活的字符数组作为成员,所以我不能在“API_init”中定义成员“char padding[sizeOfObj]”


任何关于解决我的问题或新的实现方法的建议都将不胜感激。

由于
填充
下一个
共享相同的内存(属于一个联合体),当您分配给
下一个
时,无论
填充
指向的数据都将丢失

您的解决方案是将块作为数据,或者作为指向下一个可用块的指针。因此,对于每个
malloc()
,我们需要分配
max(sizeof(union Chunk),sizeofbj)


当然,为了简洁起见,任何错误检查和小错误修复都被省略了

如果它们都具有相同的大小,为什么不使用数组和位图,这样您就可以利用缓存。您测试过代码了吗?联盟没有意义,因为成员使用相同的内存块,这意味着填充和数据将包含相同的地址。非常感谢!顺便说一句,我在C上编写了API_malloc()和API_free()。
union Chunk{
    char data[1]; /* `1` is a dummy value, the compiler doesn't actually really care 
                     if we allocate and use more than 1 char */ 
    union Chunk* next;
};


/* We return `struct Pool` by value to save a `malloc()`  (c is not java)*/ 
struct Pool API_init(size_t sizeOfObj, size_t numOfObj){

    union Chunk* prev = NULL;
    size_t chunksize = max(sizeof (union Chunk), sizeOfObj);

    /* counting upwards is easier than downwards */
    for(size_t i = 0; i < numOfObj; i++){

        /* We don't cast the return value from `malloc()`. This is c, not c++ */
        curr = malloc(chunksize);

        curr->next = prev;

        prev = curr;
    }

    struct Pool res;   
    res.nextFreeChunk = curr;
    return res;
}
struct Pool{
    char *buffer;
    Chunk* nextFreeChunk;
};

struct Pool API_init(size_t sizeOfObj, size_t numOfObj){

    size_t chunksize = max(sizeof (union Chunk), sizeOfObj);

    /* Checking for overflow is left as an exercise for the reader */
    size_t buffersize = numOfObj * chunksize;

    char *buffer = malloc(buffersize);


    for(size_t i = 0; i < numOfObj - 1; i++){

        union Chunk *curr = (union Chunk *)(buffer + i * chunksize);
        curr->next = (union Chunk *)(buffer + (i+1) * chunksize);

    }

    if (numOfObj)
    {
        union Chunk *last = (union Chunk *)(buffer + (numOfObj - 1) * chunksize);
        last->next = NULL;
    }


    struct Pool res;
    res.buffer = buffer;    
    res.nextFreeChunk = (union Chunk *)buffer;
    return res;
}