Sea*_*yne 0 c realloc dynamic-arrays
我有一个动态数组实现,我正在为泛型类型工作。我的理解是realloc的无效指针错误通常是由于没有使用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);
Run Code Online (Sandbox Code Playgroud)
数组
#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;
}
Run Code Online (Sandbox Code Playgroud)
主文件
#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;
}
Run Code Online (Sandbox Code Playgroud)
我一直在尝试修复这个错误,但我的 C 技能并不好。我在这里缺少什么?
你malloc错了:
a = malloc(sizeof a + INITIAL_SIZE * objsize);
\------/ \----------------------/
sizeof pointer some extra bytes
Run Code Online (Sandbox Code Playgroud)
这并没有一个分配空间struct array。它根据指针的大小和一些额外的字节(这里是 1*4)分配内存。
在我的系统上,上述分配是 12 个字节,但struct array需要 32 个字节。
因此分配的内存不能容纳 astruct array并且您正在访问未分配给您的内存。那么任何事情都可能发生。
有点不清楚你想用 this 实现什么malloc。“正常方式”很简单:
a = malloc(sizeof *a); // Allocate a single 'struct array'
Run Code Online (Sandbox Code Playgroud)
而且你还需要objsize像这样保存
a->obj_size = objsize;
Run Code Online (Sandbox Code Playgroud)
在new_array函数中。如果不realloc使用未初始化的变量:
realloc(a->elems, a->obj_size * a->capacity * 2);
\---------/
Currently uninitialized
Run Code Online (Sandbox Code Playgroud)
此外,这很奇怪:
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...
Run Code Online (Sandbox Code Playgroud)
我想知道你是否真的想要这样的东西:
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
Run Code Online (Sandbox Code Playgroud)
最后一点:
有时您检查 NULL 之后malloc,有时您不检查。要么每次都做,要么根本不做。