C内存池存储

时间:2016-02-27 01:17:10

标签: c pointers memory memory-management

我正在编写小内存分配系统。拥有:

typedef struct _POOL
{
    int size;     /*size of memory pool*/
    void* memory; /*pointer to pool location in memory*/
} Pool;

Pool* allocatePool(int n) {
    Pool *myPool = malloc(sizeof(Pool) + n);

    if (myPool){
        myPool->size = n;
        myPool->memory = myPool+1;
    }

    return myPool;
}

我正在尝试编写将在池中的位置偏移处存储n个大小的任意对象的函数。

void store(Pool* pool, int offset, int size, void *object) {
    char *ptrHelper;                  
    ptrHelper = &(pool->memory);      /*copy pool memory address*/
    ptrHelper += offset;              /*increment to match offset*/
    memcpy(ptrHelper, &object, size); /*copy object in to the pool*/
}

问题:

ptrHelper =&(pool-> memory)还有另一种获取池内存地址的正确方法吗?

如果我想存储的值大于void * object的大小(在我的情况下是4个字节),该怎么办?

如何正确处理字符串而不更改函数参数结构? 谢谢。

2 个答案:

答案 0 :(得分:1)

我不确定这是最好的答案,但这可能会有所帮助......:

  1. 您的结构浪费了内存空间 - 您不需要指针,因为您的内存块只是在结构的末尾继续。要轻松访问内存块,您可以使用flexible (un-specified) length array at the end of your structure, known as a FAM

  2. 我不认为你需要使用标签和typedef别名命名结构 - 这是多余的。你无论如何也不会使用结构的标签名称,所以不要使用它。

  3. 您的store函数滥用了指针。例如:object已经是指针,直接使用它(不要使用指针的地址)。同样适用于ptrHelper - 它已经是指针。

    使用指针的地址(使用&运算符)将返回指针在堆栈的内存地址中的位置< / strong>(函数中变量的位置),不是数据的位置

  4. 正如Olef指出的那样 - 你正在混合有符号和无符号值,这很危险。我已将size类型更改为size_t,这是您从size_of得到的,而且是malloc期望的内容。

    如果它对您来说太大了,您可以使用unsigned int或unsigned short,具体取决于您将使用的内容作为上限...但是,这会使错误处理有点更难管理。

  5. 这里的结构与无符号size属性相同,并且使用FAM(灵活数组成员):

    typedef struct
    {
        size_t size;     /*size of memory pool*/
        char memory[]; /* the actual memory buffer, available as a byte array */
    } Pool;
    
    // sizeof(Pool) == sizeof(size_t) // the char[] array isn't part of the size.
    

    这种微小的变化也使分配更容易:

    Pool* allocatePool(size_t n) {
        Pool *myPool = malloc(sizeof(Pool) + n);
    
        if (myPool){
            myPool->size = n;
        }
    
        return myPool;
    }
    

    需要考虑的事项 - 此结构和分配函数要求您的Pool对象的用户使用特殊语义访问内存。

    另一方面,返回pool->memory数组而不是pool对象将允许您的用户不可知,并且您可以实现直接适合的malloc替代。< / p>

    当你返回一个指针时,你只需要计算偏移量就可以找到原始pool对象在内存中的位置。

    看看Redis使用的惊人SDS String Library - 他们有很棒的想法。

    您可以使用以下方法实现类似的内容:

    #define _get_pool_addr(p) ((p) - sizeof(Pool))
    
    void* allocatePool(size_t n) {
        Pool *myPool = malloc(sizeof(Pool) + n);
    
        if (myPool){
            myPool->size = n;
        }
    
        return myPool->memory;
    }
    
    void freePool(void * pooled_memory) {
        Pool *myPool = _get_pool_addr(pooled_memory);
        // do what you want. If you're freeing the memory:
        free(myPool);
    }
    

    使用这些更改,您的store功能非常直接:

    void store(void * mymem, int offset, int size, void *object) {
        memcpy(mymem + offset, object, size); /*copy object in to the pool*/
    }
    

    我认为这比使用看起来像这样的store函数(你的版本,只是修复)会更好:

    void store(Pool* pool, int offset, int size, void *object) {
        char *ptrHelper;                  
        ptrHelper = pool->memory;      /*copy pool memory address*/
        ptrHelper += offset;              /*increment to match offset*/
        memcpy(ptrHelper, object, size); /*copy object in to the pool*/
    }
    
    祝你好运!

答案 1 :(得分:0)

$userInput未提供池内存地址。 使用:ValidateSet