Home > OS >  C dynamic array interrupted by signal SIGSEGV
C dynamic array interrupted by signal SIGSEGV

Time:01-06

I'm trying to write a dynamic array (dynamic in size and type) in C.

First I wrote a function to initialize the array. Input is a enum (TYPE) and according to value of this parameter I allocate memory for corresponding type.

This is how I initialize the array:

...

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;
}

And this is how I resize and append data to list:

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);
    }
}

And below code is initializing and appending an item to list

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

But I get this error after execution:

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

What is the problem?

CodePudding user response:

I'm guessing the main problem is this:

*(int*) value;

You pass the int value 10 to the function. It's not a valid pointer, it can't be dereferenced. Attempting to dereference 10 will lead to undefined behavior (and likely crashes).

You need to use the value as an actual value not a pointer:

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

and

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

Same problem with almost all the other cases.

The exception is for char, because it's implementation-defined if char is signed or unsigned. You need to use uintptr_t to preserve the bits as is, instead of preserving the value.

  • Related