C 动态阵列被信号 SIGSEGV 中断

C dynamic array interrupted by signal SIGSEGV

提问人:pedram 提问时间:1/5/2023 更新时间:1/5/2023 访问量:49

问:

我正在尝试用 C 编写一个动态数组(大小和类型是动态的)。

首先,我编写了一个函数来初始化数组。输入是一个枚举 (TYPE),根据此参数的值,我为相应的类型分配内存。

这是我初始化数组的方式:

...

typedef enum {
    CHAR,
    INT,
    FLOAT,
    DOUBLE,
    BOOLEAN,
} TYPE;

...

struct vector_result {
    TYPE type;
    int len;
    void* data;
};

...

struct vector_result DSTR_vector_init(TYPE type){
    void* data;
    switch (type) {
        case CHAR:
            data = (char*) malloc(0);
            break;
        case INT:
            data = (int*) malloc(0);
            break;
        case FLOAT:
            data = (float*) malloc(0);
            break;
        case DOUBLE:
            data = (double*) malloc(0);
            break;
        case BOOLEAN:
            data = (bool*) malloc(0);
            break;
        default:
            fprintf(stderr, "unknown type to initialize vector\n");
            exit(EXIT_FAILURE);
    }
    struct vector_result result;
    result.type = type;
    result.data = data;
    result.len = 0;
    return result;
}

这就是我调整大小并将数据附加到列表的方式:

void DSTR_vector_push(struct vector_result* vector, void* value){
    vector->len++;
    switch (vector->type) {
        case CHAR:
            vector->data = (char*) realloc(vector->data, get_type_size(vector->type) * vector->len);
            ((char*)vector->data)[vector->len-1] = *(char*) value;
            break;
        case INT:
            vector->data = (int*) realloc(vector->data, get_type_size(vector->type) * vector->len);
            ((int*)vector->data)[vector->len-1] = *(int*) value;
            break;
        case FLOAT:
            vector->data = (float*) realloc(vector->data, get_type_size(vector->type) * vector->len);
            ((float*)vector->data)[vector->len-1] = *(float*) value;
            break;
        case DOUBLE:
            vector->data = (double*) realloc(vector->data, get_type_size(vector->type) * vector->len);
            ((double*)vector->data)[vector->len-1] = *(double*) value;
            break;
        case BOOLEAN:
            vector->data = (bool*) realloc(vector->data, get_type_size(vector->type) * vector->len);
            ((bool*)vector->data)[vector->len-1] = *(bool*) value;
            break;
        default:
            fprintf(stderr, "unknown type to initialize vector\n");
            exit(EXIT_FAILURE);
    }
}

下面的代码正在初始化并将一个项目附加到列表中

struct vector_result int_vec = DSTR_vector_init(INT);
DSTR_vector_push(&int_vec, 10);

但是我在执行后收到此错误:

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

问题是什么?

c 向量 分割-故障 malloc realloc

评论

0赞 Allan Wind 1/5/2023
发布程序而不是片段(参见最小可重现示例)。您不需要从 realloc 中强制转换 void *。如果 realloc 失败,调用 realloc 时使用的模式将导致泄漏。你必须分配给一个临时的,看看它是否为空,然后弄清楚你想做什么。
0赞 Some programmer dude 1/5/2023
首先,它是否返回 null 指针,则定义了它的实现。无论采用哪种方式,都不能取消引用指针,即使它不是 null 指针。它只能传递给 或(或重新分配)。malloc(0)reallocfree
0赞 Some programmer dude 1/5/2023
其次,在 C 中,您不应该强制转换 malloccallocrealloc(或任何其他返回的函数)的结果。考虑到这是一个,为什么还要首先铸造?void *datavoid *
0赞 Retired Ninja 1/5/2023
在调试器中运行程序以查看其崩溃位置。如果代码在库函数中崩溃,请使用调用堆栈查找代码。使用 AddressSanitizer 等工具帮助跟踪此类问题。
2赞 Fe2O3 1/5/2023
为什么有这么多复杂的代码来初始化指向 NULL 的 void 指针......不确定那会是一个快乐的...尝试制作这样的泛型数组的问题在于,您失去了编译器的帮助,并为将 s “推”入旨在容纳 s 的数组打开了大门。malloc(0);floatchar

答:

1赞 Some programmer dude 1/5/2023 #1

我猜主要问题是这个:

*(int*) value;

将值传递给函数。它不是有效的指针,不能取消引用。尝试取消引用将导致未定义的行为(并可能崩溃)。int1010

您需要将该值用作实际,而不是指针:

DSTR_vector_push(&int_vec, (void *) (intptr_t) 10);

((int*)vector->data)[vector->len-1] = (int) (intptr_t) value;

几乎所有其他情况都存在同样的问题。

例外情况是 ,因为它是实现定义的,如果已签名或未签名。您需要按原样使用以保留,而不是保留值。charcharuintptr_t