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

对于通用内存池,如何在C中的指针之间自由转换?,c,pointers,memory-pool,C,Pointers,Memory Pool,我开始实现一个通用内存池。这是为了学习,所以肯定有很多错误。但是,我正在前进。现在我被一个新的部分绊住了。首先是守则 #include <stdlib.h> #include <string.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> typedef enum { FALSE, TRUE } BOOL; typedef struct mem_block

我开始实现一个通用内存池。这是为了学习,所以肯定有很多错误。但是,我正在前进。现在我被一个新的部分绊住了。首先是守则

#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;
}
c3
这里是使用
pool\u allocate
分配的,结果是指向数据的指针,
uint8*。因此,
c3
指向一个复杂的对象。解引用应该给出实际数据,我认为这是可行的。但它也有自己的地址。我假设这个地址与它的块的
数据
指针相同,因为它是
内存块
中的第一个成员。所以我将它自由地浇铸到一个
mem\u块*
。但这是行不通的

printf("Position of c3 is %ld\n", cur->pool_position);
表示c3的
位置为0
或其他胡言乱语。我希望看到像16、32之类的东西,因为每个
mem_块都是16字节。那么,你为什么认为演员阵容

mem_block* cur = (mem_block *) &c3;

不允许我像处理
mem_块一样处理
c3
?也许我没有通过引用正确地传递指针,所以指向的东西的更改在外部看不到?这似乎不太可能,因为我可以按预期处理分配的对象,但谁知道呢?我检查了每个部分,但仍然无法解决问题。

在malloc中的工作方式是,每个块都有一个头(管理结构),在alloc上,您返回该结构之后的地址。然后在空闲时,你知道你的地址在报头之后,所以你可以从中计算出实际报头的地址

一个简单的技巧就是使用

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;
    ...
}
void alloc(大小){
...
结构内存块*块=
返回和阻塞[1];
}
无无效(无效*添加){
struct mem_block*block=addr;
块[-1]。is_freed=false;
...
}

您希望cur
包含什么内容?您的cast基本上需要8个字节,这些字节构成了
复杂的
结构,并试图将其解释为一个更大的
mem_块
结构(布局和类型不兼容),从而导致字段值杂乱无章。此外,如果您从代码中删除所有内容并只保留,效果会更好。特别是,整个内存池看起来不相关,因为您只关心特定的强制转换。
c3
是一个局部变量-它的位置,
&c3
,不是池中的地址。它的值,
c3
,是。你使用了太多的施法。它防止编译器警告您无效转换(您有很多)。大多数(如果不是全部的话)类型转换似乎也完全没有必要。你确定你是用C语言编译的吗?一致的C编译器应该在
mem_pool*GLOBAL_pool=pool_init()上阻塞,因为全局变量的动态初始化是C++的事情。另一方面,在C语言中使用malloc是没有用的。
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;
    ...
}