gpt4 book ai didi

c - 对于通用内存池,如何在 C 中的指针之间自由转换?

转载 作者:太空宇宙 更新时间:2023-11-04 03:16:54 26 4
gpt4 key购买 nike

我开始实现通用内存池。这是出于学习目的,所以肯定有很多错误。但是,我正在前进。现在我被困在一个新的部分。一、代码

#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

typedef enum { FALSE, TRUE } BOOL;

typedef struct mem_block {
uint8_t* data;
size_t block_size;
size_t pool_position;
BOOL is_freed;
} mem_block;

typedef struct mem_pool {
mem_block* blocks;
size_t index;
size_t pool_size;
} mem_pool;

mem_pool *pool_init() {
mem_pool *pool = (mem_pool *) malloc(sizeof(mem_pool));
pool->pool_size = (size_t) 128;
mem_block* blk = (mem_block *) malloc(pool->pool_size * sizeof (mem_block));
pool->index = 0;
pool->blocks = blk;

return pool;
}

void *pool_allocate(mem_pool **pool, size_t size) {
mem_pool* _pool = *pool;
size_t free_portion = _pool->pool_size - _pool->index;

if(size < free_portion){
mem_block* allocated_blk = _pool->blocks + _pool->index;
uint8_t* data = (uint8_t*) malloc(size * sizeof(uint8_t));
allocated_blk->data = data;
allocated_blk->block_size = size;
allocated_blk->is_freed = FALSE;
allocated_blk->pool_position = _pool->index;
_pool->index += size;
return (void *) allocated_blk->data;
}
else{
printf("Pool is out of memory");
return NULL;
}
}

/*void pool_free(mem_pool **pool, void *block) {
mem_block* cur = (mem_block*) block;
mem_block* next = cur + 1;
// override the unneeded memory
memmove(cur, next, (*pool)->pool_size - next->pool_position);
}*/

typedef struct complex {
double i;
double r;
} complex;

mem_pool *GLOBAL_POOL = pool_init();
int main() {
complex *c1 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c1->r = 1.0;
c1->i = 2.0;
printf("Value is (%f + %fi)\n", c1->r, c1->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

complex *c2 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c2->r = 2.0;
c2->i = 3.0;
printf("Value is (%f + %fi)\n", c2->r, c2->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

mem_block* cur = (mem_block *) &c2;
printf("Position of c2 is %ld\n", cur->pool_position);
printf("Adress of c2's block is %x\n", cur);
printf("Address of c2 is %x\n", &c2);
printf("c2 points to %x\n", c2);

complex *c3 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c3->r = 3.0;
c3->i = 4.0;
printf("Value is (%f + %fi)\n", c3->r, c3->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

cur = (mem_block *) &c3;
printf("Position of c3 is %ld\n", cur->pool_position);
printf("Adress of c3's block is %x\n", cur);
printf("Address of c3 is %x\n", &c3);
printf("c3 points to %x\n", c3);

complex *c4 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c4->r = 4.0;
c4->i = 5.0;
printf("Value is (%f + %fi)\n", c4->r, c4->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

complex *c5 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c5->r = 5.0;
c5->i = 6.0;
printf("Value is (%f + %fi)\n", c5->r, c5->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

complex *c6 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c6->r = 6.0;
c6->i = 7.0;
printf("Value is (%f + %fi)\n", c6->r, c6->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

complex *c7 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
c7->r = 7.0;
c7->i = 8.0;
printf("Value is (%f + %fi)\n", c7->r, c7->i);
printf("Remaining free size is %ld\n", GLOBAL_POOL->pool_size - GLOBAL_POOL->index);

complex *c8 = (complex *) pool_allocate(&GLOBAL_POOL, sizeof(complex));
if(c8 != NULL) {
c8->r = 3.0;
c8->i = 4.0;
printf("Value is (%f + %fi)\n", c8->r, c8->i);
}else {
return -1;
}
return 0;
}

目前,它的大小是 128 字节,但一旦我掌握了基础知识,我就会将其设置为无限大小。分配可能工作正常,您可以看到输出并看到我可以设置分配的指针并使用该值。最重要的是,我想实现 free .它在注释掉的函数中 pool_free .执行 memmove , 我需要知道 mem_block 的索引我正在删除。

pool_allocate ,你可以看到我返回了 data分配 block 的指针,而不是整个 block 的指针,因此它可以像常规 malloc 一样使用.这意味着,释放时,我需要恢复 mem_block从数据指针。为了能够做到这一点,我把 data指针作为 mem_block 的第一个元素.

让我进一步解释代码

mem_block* cur = (mem_block *) &c3;
printf("Position of c3 is %ld\n", cur->pool_position);
printf("Adress of c3's block is %x\n", cur);
printf("Address of c3 is %x\n", &c3);
printf("c3 points to %x\n", c3);

c3这里是使用 pool_allocate 分配的和指向数据的结果指针,uint8_t*实际上被转换为 complex *要使用的。所以c3指向 complex目的。取消引用应该给出实际数据,我认为这可行。但它也有自己的地址。我认为这个地址与 data 相同它 block 的指针,因为它是 mem_block 中的第一个成员.所以我把它自由地转换到 mem_block* .但这不起作用。

printf("Position of c3 is %ld\n", cur->pool_position);

Position of c3 is 0或其他乱码。我期待看到像 16、32 等这样的东西,因为每个 mem_block是16个字节。那么,为什么你认为 Actor

mem_block* cur = (mem_block *) &c3;

不会让我使用 c3就好像它是一个 mem_block ?也许我没有正确地通过引用传递指针,所以指向的东西的变化在外面是不可见的?这似乎不太可能,因为我可以按预期使用分配的对象,但谁知道呢?我检查了每个部分,但仍然无法解决问题。

最佳答案

这在 malloc 中的工作方式是每个 block 都有一个 header (管理结构),在 alloc 上你返回该结构之后的地址。然后在 free 上,您知道 header 后有地址,因此您可以从中计算出实际 header 的地址。

一个简单的技巧是使用

void alloc(size_t size) {
...
struct mem_block *block = <address of block you return>
return &block[1];
}

void free(void *addr) {
struct mem_block *block = addr;
block[-1].is_freed = false;
...
}

关于c - 对于通用内存池,如何在 C 中的指针之间自由转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50583529/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com