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 初始化为零。
所以我正在尝试实现一个简单的内存池作为大学作业的一部分,但是我 运行 遇到了在我分配的内存中存储值的问题。
这是我的 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 初始化为零。