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.