我正在编写小内存分配系统。拥有:
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个字节),该怎么办?
如何正确处理字符串而不更改函数参数结构? 谢谢。
答案 0 :(得分:1)
我不确定这是最好的答案,但这可能会有所帮助......:
您的结构浪费了内存空间 - 您不需要指针,因为您的内存块只是在结构的末尾继续。要轻松访问内存块,您可以使用flexible (un-specified) length array at the end of your structure, known as a FAM。
我不认为你需要使用标签和typedef别名命名结构 - 这是多余的。你无论如何也不会使用结构的标签名称,所以不要使用它。
您的store
函数滥用了指针。例如:object
已经是指针,直接使用它(不要使用指针的地址)。同样适用于ptrHelper
- 它已经是指针。
使用指针的地址(使用&
运算符)将返回指针在堆栈的内存地址中的位置< / strong>(函数中变量的位置),不是数据的位置。
正如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
替代。< / 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