【问题标题】:C memory pool storing [closed]C内存池存储[关闭]
【发布时间】:2016-02-27 01:17:09
【问题描述】:

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

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 个字节),该怎么办?

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

【问题讨论】:

  • 为什么是&(pool->memory) 而不是pool->memory?似乎pool->memory 已经是指向池的指针。为什么要取它的地址?如果offset为0,你不会覆盖pool->memory吗?
  • pool->memory 是我的池的基地址。增加它的地址会更改我的池的地址并将偏移量设置为 0 对我的目标地址没有任何作用。我可能错了。这些是我进入 C 的第一步 :)。
  • 这是第二次转发!仅供参考:我将其标记为 mod 注意。堆栈溢出不是一个教程网站。如果您缺乏基础知识,请阅读 C 书籍并从更简单的内容开始练习。
  • @Olaf 我与版主讨论了我的帖子。我们得出的结论是我应该删除我以前的帖子并重新提出我的问题。所以我做到了。
  • 您应该在问题中提到这一点。不管怎样,我们会看看一个模组能做什么;我仍然认为你的问题太宽泛了(显然我不是唯一一个)。无意冒犯(老实说!),但是您确实应该首先在 C 中进行更多练习,并学习如何在 C 中做一些事情。内存管理包括相当多的不严格标准兼容操作的部分,初学者应该明确避免。我已经看到了各种——嗯——“有问题的”问题。而且您的代码部分不符合实际上应该!

标签: c pointers memory memory-management


【解决方案1】:

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

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

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

  3. 您的 store 函数滥用了指针。例如:object已经是一个指针,直接使用(不要取指针的地址)。 ptrHelper 也是如此 - 它已经是一个指针。

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

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

    如果它对您来说太大,您可以使用 unsigned int 或 unsigned short,这取决于您将使用什么作为上限...但是,这会使错误处理更难管理。

下面是具有无符号 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 替代方案。

当你得到一个指针返回时,你只需要计算偏移量就可以找到原始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*/
}

祝你好运!

【讨论】:

  • 相当努力,但仍有一些缺陷。首先:混合有符号和无符号整数应该非常小心。 sizeof 运算符产生size_t,它不应与int 混合使用。一般注意事项:做 OP 的工作是个坏主意。最好给出一些提示并解释她遇到的问题,以便他可以自己编写代码。否则他不会真正学习。
  • “使用未命名的结构” - 没有“未命名的结构”。
  • @Olaf - 谢谢。我只是在修复与问题相关的部分(不是int v.s size_t),所以感谢您的关注。至于 OP 的工作......我认为他/她已经完成了大部分工作,只是在指针使用方面存在问题(以及类型不匹配,我忽略了)......但下次我会记住它。
  • 我实际上并没有看到这个问题有多大用处。那不是内存管理,只是在分配的块中添加一个不必要的size。不必要,因为 free 不需要它。顺便说一句,你的代码也是错误的。 void * 上的算术未定义。而且您还有其他未定义的对齐问题行为。如果函数可以完成相同的工作,也不要使用宏。如果对性能有疑问(对于早期代码,大多数情况下是个坏主意),请将其设为 static 和/或 inline
  • @Olaf - 谢谢!我想我通过这个答案学到的东西比提问的人更多:-)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 2011-06-28
    • 2019-01-07
    • 2014-07-06
    相关资源
    最近更新 更多