C realloc() 无效指针错误,即使使用了 malloc
C realloc() Invalid Pointer Error even though malloc was used
我正在为泛型类型开发一个动态数组实现。我的理解是realloc的invalid pointer错误一般是没有用malloc分配原始指针导致的,但是我用的是malloc
这是我的 array.h 代码
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
struct array {
void *elems;
size_t obj_size;
size_t size;
size_t capacity;
};
struct array* new_array(size_t objsize);
int push_back(struct array* a, const void* value);
Array.c
#include "array.h"
#include <stdio.h>
#include <string.h>
#define INITIAL_SIZE (1)
#define ARR_AT(a, i) ((void *) ((char *) (a)->elems + (i) * (a)->obj_size))
struct array* new_array(size_t objsize) {
struct array* a;
a = malloc(sizeof a + INITIAL_SIZE * objsize);
if (!a) { return NULL; }
a->elems = malloc(objsize);
a->capacity = 1;
a->size = 0;
return a;
}
int push_back(struct array* a, const void* value) {
if (a->size == a->capacity) {
void* temp = realloc(a->elems, a->obj_size * a->capacity * 2);
a->elems = temp;
if (!a) { return -1; }
a->capacity = a->capacity * 2;
}
memcpy(ARR_AT(a, a->size), value, a->obj_size);
a->size++;
return 0;
}
main.c
#include "array.h"
#include <stdio.h>
int main(void) {
struct array* a = new_array(4);
uint32_t* b = (uint32_t*) 3;
push_back(a, b);
printf("Size: %ld \n", a->size);
for (int i = 0; i < 30; i++) {
push_back(a, b + i);
printf("Size: %ld \n", a->size);
}
return 0;
}
我一直在尝试修复这个错误,但我的 C 技能很差。我在这里错过了什么?
你的malloc
是错误的:
a = malloc(sizeof a + INITIAL_SIZE * objsize);
\------/ \----------------------/
sizeof pointer some extra bytes
这 不会 为 struct array
分配 space。它分配与指针大小和一些额外字节(此处为 1*4)相对应的内存。
在我的系统上,上述分配是 12 个字节,但 struct array
需要 32 个字节。
因此分配的内存无法容纳 struct array
,您正在访问未分配给您的内存。那么任何事情都有可能发生。
有点不清楚你想用这个 malloc
实现什么。 “正常方式”很简单:
a = malloc(sizeof *a); // Allocate a single 'struct array'
而且你还需要收藏objsize
喜欢
a->obj_size = objsize;
在 new_array
函数中。如果不这样做,realloc
使用未初始化的变量:
realloc(a->elems, a->obj_size * a->capacity * 2);
\---------/
Currently uninitialized
而且这很奇怪:
uint32_t* b = (uint32_t*) 3; // Converting the number 3 to a pointer !?
push_back(a, b); // and then push_back uses that pointer
// in memcpy... that has to fail...
我想知道你是否真的想要这样的东西:
uint32_t b = 3; // Make an ordinary uint variable with value 3
push_back(a, &b); // Pass a pointer to the variable b so that
// the raw data representing the value 3 can be
// copied to "struct array"->elems
最后一点:
有时您会在 malloc
之后检查 NULL,有时则不会。要么每次都做,要么根本不做。
我正在为泛型类型开发一个动态数组实现。我的理解是realloc的invalid pointer错误一般是没有用malloc分配原始指针导致的,但是我用的是malloc
这是我的 array.h 代码
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
struct array {
void *elems;
size_t obj_size;
size_t size;
size_t capacity;
};
struct array* new_array(size_t objsize);
int push_back(struct array* a, const void* value);
Array.c
#include "array.h"
#include <stdio.h>
#include <string.h>
#define INITIAL_SIZE (1)
#define ARR_AT(a, i) ((void *) ((char *) (a)->elems + (i) * (a)->obj_size))
struct array* new_array(size_t objsize) {
struct array* a;
a = malloc(sizeof a + INITIAL_SIZE * objsize);
if (!a) { return NULL; }
a->elems = malloc(objsize);
a->capacity = 1;
a->size = 0;
return a;
}
int push_back(struct array* a, const void* value) {
if (a->size == a->capacity) {
void* temp = realloc(a->elems, a->obj_size * a->capacity * 2);
a->elems = temp;
if (!a) { return -1; }
a->capacity = a->capacity * 2;
}
memcpy(ARR_AT(a, a->size), value, a->obj_size);
a->size++;
return 0;
}
main.c
#include "array.h"
#include <stdio.h>
int main(void) {
struct array* a = new_array(4);
uint32_t* b = (uint32_t*) 3;
push_back(a, b);
printf("Size: %ld \n", a->size);
for (int i = 0; i < 30; i++) {
push_back(a, b + i);
printf("Size: %ld \n", a->size);
}
return 0;
}
我一直在尝试修复这个错误,但我的 C 技能很差。我在这里错过了什么?
你的malloc
是错误的:
a = malloc(sizeof a + INITIAL_SIZE * objsize);
\------/ \----------------------/
sizeof pointer some extra bytes
这 不会 为 struct array
分配 space。它分配与指针大小和一些额外字节(此处为 1*4)相对应的内存。
在我的系统上,上述分配是 12 个字节,但 struct array
需要 32 个字节。
因此分配的内存无法容纳 struct array
,您正在访问未分配给您的内存。那么任何事情都有可能发生。
有点不清楚你想用这个 malloc
实现什么。 “正常方式”很简单:
a = malloc(sizeof *a); // Allocate a single 'struct array'
而且你还需要收藏objsize
喜欢
a->obj_size = objsize;
在 new_array
函数中。如果不这样做,realloc
使用未初始化的变量:
realloc(a->elems, a->obj_size * a->capacity * 2);
\---------/
Currently uninitialized
而且这很奇怪:
uint32_t* b = (uint32_t*) 3; // Converting the number 3 to a pointer !?
push_back(a, b); // and then push_back uses that pointer
// in memcpy... that has to fail...
我想知道你是否真的想要这样的东西:
uint32_t b = 3; // Make an ordinary uint variable with value 3
push_back(a, &b); // Pass a pointer to the variable b so that
// the raw data representing the value 3 can be
// copied to "struct array"->elems
最后一点:
有时您会在 malloc
之后检查 NULL,有时则不会。要么每次都做,要么根本不做。