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);
Другие вопросы по тегам