C memcpy 导致分段错误

C memcpy causing segmentation fault

所以我正在尝试实现一个简单的内存池作为大学作业的一部分,但是我 运行 遇到了在我分配的内存中存储值的问题。

这是我的 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 的行。我不确定问题出在哪里,因为我确定我将正确的值传递给函数,但是每次我尝试 运行 程序时都会出现分段错误。

问题的原因可能是什么?

改变这个:

Pool* pool = (Pool*)malloc(sizeof(Pool*));

对此:

Pool* pool = malloc(sizeof Pool);

问题出在这里:

Pool* pool = (Pool*)malloc(sizeof(Pool*));

在 32 位系统上 sizeof(Pool*)==4。这是因为 Pool* 参数表示您需要指向 Pool 的指针的大小。指针大小是恒定的(32 位为 4,64 位为 8)。应该是:

Pool* pool = (Pool*)malloc(sizeof(Pool));

在这种情况下,Pool 结构的大小将被发送到 malloc。我在您的代码中注意到的另一件事。这本身不是错误,但它是零影响的代码:

while(i < pool->size_bytes)
{
    void* temp = (int*)pool->data + i++;
    temp = 0;
}

您将临时指针设置为 NULL,本质上,不是将它指向的变量设置为 0。这意味着您的 pool->data 永远不会被初始化。一种修改方法:

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;

您还需要修正在 allocate_pool 中调用 malloc() 的方式:

Pool* pool = malloc(sizeof Pool);

您的代码只是为一个指针分配了足够的 space,而不是整个 Pool 结构。

while 循环看起来试图将 data 初始化为零也是错误的。您可以简单地使用 memset:

memset(pool->data, 0, size_bytes);

您也可以使用 calloc() 而不是 malloc() 来分配 space,因为它会自动将 space 初始化为零。