C memcpy导致分段错误

时间:2016-02-19 21:57:00

标签: c memory-management malloc memcpy memory-pool

所以我试图将一个简单的内存池作为大学作业的一部分来实现,但是我已经遇到了将值存储在我已经分配的内存中的问题。

这是我的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);
}

只要我打电话给&#39; store_in_pool&#39;就会出现问题。其中包含一个调用memcpy的行。我不确定问题是什么,因为我确定我将正确的值传递给函数,但是每次尝试运行程序时都会发生分段错误。

问题可能是什么原因?

3 个答案:

答案 0 :(得分:2)

问题在于:

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-&gt;数据永远不会被初始化。修改它的一种方法:

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。

答案 1 :(得分:2)

由于这个原因,分段错误正在发生:

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()来分配空间,因为它会自动将空间初始化为零。

答案 2 :(得分:1)

改变这个:

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

到此:

Pool* pool = malloc(sizeof Pool);