C memcpy вызывает ошибку сегментации
Поэтому я пытаюсь реализовать простой пул памяти как часть задания для Университета, однако я столкнулся с проблемой хранения значений в выделенной памяти.
Это мой файл main.c:
#include <stdio.h>
#include "Pool.h"
int main(int argc, char** argv)
{
Pool* pool = allocate_pool(64);
printf("Pool Size: %d bytes...\n", pool->size_bytes);
int* a = (int*)100;
store_in_pool(pool, 20, sizeof(int), a);
void* ap = retrieve_from_pool(pool, 20, sizeof(int));
printf("%d\n", ap);
free_pool(pool);
return 0;
}
Мой файл Pool.h:
#ifndef ASSIGNMENT_2_POOL_H
#define ASSIGNMENT_2_POOL_H
typedef struct MemoryPool
{
int size_bytes;
void* data;
} Pool;
Pool* allocate_pool(int size_bytes);
void free_pool(Pool* pool);
void store_in_pool(Pool* pool, int offset_bytes, int size_bytes, void* object);
void* retrieve_from_pool(Pool* pool, int offset_bytes, int size_bytes);
#endif
И мой файл Pool.c:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "Pool.h"
Pool* allocate_pool(int size_bytes)
{
Pool* pool = (Pool*)malloc(sizeof(Pool*));
pool->size_bytes = size_bytes;
pool->data = malloc(size_bytes);
int i = 0;
while(i < pool->size_bytes)
{
void* temp = (int*)pool->data + i++;
temp = 0;
}
return pool;
}
void free_pool(Pool* pool)
{
free(pool->data);
free(pool);
}
void store_in_pool(Pool* pool, int offset_bytes, int size_bytes, void* object)
{
memcpy((void*)((char*)pool->data + offset_bytes), object, size_bytes);
}
void* retrieve_from_pool(Pool* pool, int offset_bytes, int size_bytes)
{
return (void*)((char*)pool->data + offset_bytes);
}
Проблема возникает всякий раз, когда я вызываю 'store_in_pool', который содержит строку, которая вызывает memcpy. Я не уверен, в чем проблема, поскольку я уверен, что передаю правильные значения функции, однако ошибка сегментации возникает каждый раз, когда я пытаюсь запустить программу.
Что может быть причиной проблемы?
3 ответа
Проблема здесь:
Pool* pool = (Pool*)malloc(sizeof(Pool*));
В 32-битных системах sizeof(Pool*)==4. Это связано с тем, что аргумент Pool * указывает, что вам нужен размер указателя на Pool. Размеры указателя постоянны (4 на 32 бита, 8 на 64 бита). Так должно быть:
Pool* pool = (Pool*)malloc(sizeof(Pool));
В этом случае размер структуры Pool будет отправлен в malloc. Еще одна вещь, которую я заметил в вашем коде. По сути, это не ошибка, но это код с нулевым эффектом:
while(i < pool->size_bytes)
{
void* temp = (int*)pool->data + i++;
temp = 0;
}
Вы устанавливаете временный указатель на NULL, по существу, не устанавливая переменную, на которую он указывал на 0. Это означает, что ваш пул-> данные никогда не инициализируется. Один из способов изменить это:
while(i < pool->size_bytes)
{
char* temp = (char*)pool->data + i++;
*temp = 0;
}
Или просто:
memset(pool->data, 0, pool->size_bytes);
Или просто перехватите его у источника и удалите код инициализации, если все, что вам нужно, это инициализация до 0:
pool->data = calloc(1, pool->size_bytes);
В этом случае calloc устанавливает все байты в 0.
Ошибка сегментации происходит из-за этого:
int* a = (int*)100;
Это устанавливает a
быть указателем на адрес 100
, который не является частью вашей доступной памяти. Поэтому, когда вы затем пытаетесь скопировать с этого адреса с memcpy()
Вы получаете ошибку.
Если ты хочешь a
указывать на целое число со значением 100
правильный путь:
int aval = 100;
int *a = &aval;
Вы также должны исправить способ звонка malloc()
в allocate_pool
:
Pool* pool = malloc(sizeof Pool);
Ваш код просто выделяет достаточно места для указателя, а не всего Pool
состав.
while
цикл, который выглядит так, как будто он пытается инициализировать data
в ноль тоже неправильно. Вы можете просто использовать memset
:
memset(pool->data, 0, size_bytes);
Вы могли бы также использовать calloc()
вместо malloc()
выделить пространство, так как оно автоматически инициализирует пространство в нули.
Изменить это:
Pool* pool = (Pool*)malloc(sizeof(Pool*));
к этому:
Pool* pool = malloc(sizeof Pool);