I tried implementing a dynamic array in C but I get seg faults.
Through logging I found out that after resizing I sometimes get a random big length and capacity value. The seg fault comes from trying to access the array at the big random length to append a item.
This is some of my code:
/**
* @brief dynamic_array_default_type_value - macro to get the default type value
* @param TYPE - the type of elements to store in the array
* @return the default value of the type
*/
#define dynamic_array_default_type_value(TYPE)
(TYPE){ 0 }
/**
* @brief dynamic_array_create_default - macro to create a new dynamic array of a specific type
* @param TYPE - the type of elements to store in the array
* @return a pointer to the newly created dynamic array
*/
#define dynamic_array_create(TYPE)
(TYPE*)_dynamic_array_create(sizeof(TYPE), DYNAMIC_ARRAY_INIT_CAPACITY)
/**
* @brief dynamic_array_append - macro to append a value to the dynamic array
* @param dynamic_array - a pointer to the dynamic array
* @param value - the value to append to the array
*/
#define dynamic_array_append(dynamic_array, value)
{
if (_dynamic_array_update((dynamic_array_t*)&dynamic_array)) {
dynamic_array_header_t* dynamic_array_header = _dynamic_array_get_header(dynamic_array);
((typeof(value)*)dynamic_array)[dynamic_array_header->length++] = value;
}
}
/* (see _dynamic_array_resize()) */
#define dynamic_array_resize(dynamic_array, capacity)
_dynamic_array_resize((dynamic_array_t*)&dynamic_array, capacity)
/**
* @brief _dynamic_array_create - creates a new dynamic array with a given type size
* @param type_size - the size of the type to store in the array
* @return a pointer to the newly created dynamic array
*/
static dynamic_array_t _dynamic_array_create(size_t type_size, size_t init_capacity) {
dynamic_array_header_t* dynamic_array_header = calloc(1, sizeof(dynamic_array_header_t) + init_capacity * type_size); // set length and capacity to 0 with calloc
if (!dynamic_array_header) {
return NULL;
}
dynamic_array_header->capacity = init_capacity;
dynamic_array_header->type_size = type_size;
return (dynamic_array_t)((char*)dynamic_array_header + sizeof(dynamic_array_header_t)); // cast to char* to avoid warning
}
/**
* @brief _dynamic_array_get_header - gets the header of a given dynamic array
* @param dynamic_array - the dynamic array
* @return a pointer to the header of the dynamic array
*/
static dynamic_array_header_t* _dynamic_array_get_header(const dynamic_array_t dynamic_array) {
return (dynamic_array_header_t*)((char*)dynamic_array - sizeof(dynamic_array_header_t)); // cast to char* to avoid warning
}
/**
* @brief _dynamic_array_resize_check - checks if the dynamic array needs resizing
* @param dynamic_array_header - the header of the dynamic array
* @return true if resizing is needed, false otherwise
*/
static bool _dynamic_array_resize_check(const dynamic_array_header_t* dynamic_array_header) {
if (!dynamic_array_header) return false;
if (dynamic_array_header->capacity - dynamic_array_header->length <= 0) {
return true;
}
return false;
}
/**
* @brief _dynamic_array_resize - resizes the dynamic array to accommodate more elements
* @param dynamic_array - a pointer to the dynamic array
* @param new_capacity - the new capacity of the dynamic array
* @return true if resizing was successful, false otherwise
*/
static bool _dynamic_array_resize(dynamic_array_t* dynamic_array, size_t new_capacity) {
if (!dynamic_array || !*dynamic_array) return false;
dynamic_array_header_t* dynamic_array_header = _dynamic_array_get_header(*dynamic_array);
dynamic_array_header_t* new_header = realloc(dynamic_array_header, new_capacity * dynamic_array_header->type_size + sizeof(dynamic_array_header_t));
if (!new_header) {
return false;
}
*dynamic_array = (char*)new_header + sizeof(dynamic_array_header_t);
new_header->capacity = new_capacity;
return true;
}
/**
* @brief _dynamic_array_update - updates the dynamic array, resizing if necessary
* @param dynamic_array - a pointer to the dynamic array
* @return true if the update was successful, false otherwise
*/
static bool _dynamic_array_update(dynamic_array_t* dynamic_array) {
if (!dynamic_array || !*dynamic_array) return false;
dynamic_array_header_t* dynamic_array_header = _dynamic_array_get_header(*dynamic_array);
if (_dynamic_array_resize_check(dynamic_array_header)) {
size_t new_capacity = (dynamic_array_header->capacity == 0) ? 1 : (dynamic_array_header->capacity * 2);
if (!_dynamic_array_resize(dynamic_array, new_capacity)) return false;
}
return true;
}
Sorry for that much code but I just dont know where the problem could be.