C 内存池存储

C 内存池存储,c,pointers,memory,memory-management,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){ myP

我正在写小型内存分配系统。具有:

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*对象大小的值(我的情况下为4字节),该怎么办

如何在不改变函数参数结构的情况下正确处理字符串? 谢谢。

ptrHelper=&(池->内存)
没有给出池内存地址。
使用:
ptrHelper=pool->memory

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

  • 您的结构正在浪费内存空间—您不需要指针,因为您的内存块只是在结构的末尾继续。要轻松访问内存块,可以使用

  • 我认为不需要同时使用标记和typedef别名来命名结构-t是多余的。无论如何,您都不会使用结构的标记名,所以不要使用

  • 您的
    store
    函数误用了指针。例如:
    对象
    已经是指针,请直接使用它(不要使用指针的地址)。这同样适用于
    ptrHelper
    ——它已经是一个指针了

    获取指针地址(使用
    运算符)将返回指针在堆栈内存地址中的位置(函数中变量的位置),而不是数据的位置

  • 正如Olef所指出的,您混合了有符号和无符号的值,这是危险的。我已将
    size
    类型更改为
    size\u t
    ,这是您从
    size\u of
    中得到的,也是
    malloc
    所期望的

    如果它对您来说太大,您可以使用无符号int或无符号short,这取决于您将使用的上限。。。然而,这将使错误处理变得更难管理

  • 下面是使用无符号
    size
    属性并使用FAM(灵活数组成员)的相同结构:

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

    Pool* allocatePool(size_t n) {
        Pool *myPool = malloc(sizeof(Pool) + n);
    
        if (myPool){
            myPool->size = n;
        }
    
        return myPool;
    }
    
    需要考虑的是—此结构和分配函数要求
    对象的用户使用特殊语义访问内存

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

    当返回指针时,只需计算偏移量即可找到原始
    对象在内存中的位置

    看看Redis使用的神奇工具吧——它们有很棒的想法

    您可以使用以下方法实现类似的功能:

    #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
    函数要好(您的版本,刚刚修复):


    祝你好运

    为什么
    &(池->内存)
    而不是
    池->内存
    ?似乎
    pool->memory
    已经是指向池的指针。为什么取它的地址?如果
    偏移量
    为0,是否覆盖
    池->内存
    ?池->内存是我池的基址。增加它的地址会更改我的池的地址,而将offset设置为0不会更改我的目标地址。我可能错了。这是我进入C:)的第一步。这是第二次重新发布!仅供参考:我将其标记为mod注意。堆栈溢出不是教程站点。如果你缺乏基础知识,请阅读一本C语言书,先从一些更容易练习的东西开始。@Olaf我和版主谈过我的帖子。我们得出结论,我应该删除以前的帖子,重新措辞我的问题。是的。你应该在你的问题中提到这一点。不管怎样,我们将看看mod做了什么;我仍然认为你的问题过于宽泛(显然我不是唯一一个)。无意冒犯(老实说!),但您确实应该首先在C语言中进行更多的练习,并学习如何在C语言中做一些事情。内存管理包括许多不严格符合标准的操作,初学者应该避免这些操作。我已经看到了各种各样的问题。而你的代码在某些部分是不一致的,这实际上是应该的!虽然付出了不少努力,但仍然存在一些缺陷。对于初学者:混合有符号整数和无符号整数应该非常小心地处理。
    sizeof
    运算符生成一个
    size\u t
    ,它不应与
    int
    混合使用。总的来说,做OP的工作是个坏主意。最好给出一些提示并解释她遇到的问题,这样他就可以自己编写代码了。否则,他将无法真正学习。“使用未命名结构”-没有“未命名结构”。@Olaf-谢谢。我刚刚修复了与问题相关的部分(而不是
    int
    v.s
    size\u t
    ),因此感谢您的关注。至于OP的工作。。。我认为他/她已经完成了大部分工作,只是在指针使用方面有问题(我忽略了类型不匹配)。。。但是下次我会记住的。我觉得这个问题没有多大用处。这不是内存管理,只是向分配的块添加不必要的
    大小。不必要,因为
    free
    不需要它。顺便说一句,你的代码也错了。
    void*
    上的算术未定义。还有其他未定义的行为与对齐问题。如果函数可以执行相同的任务,也不要使用宏。如果对性能有疑问(大多数情况下,早期代码是个坏主意),请将其设置为
    静态
    和/或
    内联
    @Olaf-谢谢!我想,通过这个答案,我学到了比提问者更多的东西:——)
    void store(void * mymem, int offset, int size, void *object) {
        memcpy(mymem + offset, object, size); /*copy object in to the pool*/
    }
    
    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*/
    }