Я начинаю реализовывать общий пул памяти.Это для целей обучения, так что, безусловно, есть множество ошибок.Но я двигался вперед.Теперь я застрял в новой части.Во-первых, код
#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
выделенного блока, а не весь объект, так что его можно использовать аналогично обычному 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
его блока, поскольку он является первым членом в mem_block
.Таким образом, я свободно произвёл его на mem_block*
.Но это не работает.
printf("Position of c3 is %ld\n", cur->pool_position);
говорит Position of c3 is 0
или другой бред.Я ожидаю увидеть такие вещи, как 16, 32 и т. Д., Поскольку каждый mem_block
составляет 16 байтов.Итак, почему вы думаете, что приведение
mem_block* cur = (mem_block *) &c3;
не позволит мне работать с c3
, как если бы это было mem_block
?Может быть, мне не удается правильно передать указатель по ссылке, чтобы изменения в указанных объектах не были видны снаружи?Это кажется маловероятным, поскольку я могу работать с выделенными объектами, как ожидается, но кто знает?Я проверил каждую часть, но все еще не мог решить проблему.