C realloc() 无效指针错误即使使用了 malloc

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 技能并不好。我在这里缺少什么?

438*_*427 5

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,有时您不检查。要么每次都做,要么根本不做。