Reputation: 21
i'm working about dynamic array lists in c. i've some problems when i try to re-add one element to one arraylist after the deallocation.
Struct:
typedef struct array_list{
void** array;
size_t size;
size_t capacity;
}array_list_t;
Free array method:
void* array_list_free(array_list_t* array) {
free(array->array);
free(array);
array->capacity = 0;
array->size = 0;
array->array = NULL;
}
Allocate and reallocate method:
void array_list_check_and_realloc(array_list_t* array) {
if(!(array->capacity > array->size)) {
if(array->capacity == 0){
//the problem is probably here
array->capacity++;
array->array = realloc(array->array, sizeof(void*) * array->capacity);
}else{
array->capacity *= 2;
array->array = realloc(array->array, sizeof(void*) * array->capacity);
}
}
}
Insert element to arraylist:
void* array_list_insert(array_list_t* array, void* element) {
array_list_check_and_realloc(array);
size_t i;
for( i = array_list_size(array); i > 0; --i ) {
array->array[i] = array->array[i-1];
}
array->array[i] = element;
array->size += 1;
}
Main:
array_list_insert(array,8);
array_list_free(array);
array_list_insert(array,8); // <--- Segmentation Fault
When i try to run the program, i haven't any error by the terminal and seems work fine. But when i try use the debugger i can see the segmentation fault and i don't know why (i use CLion IDE) sorry, i'm beginner in c language ^^'
Upvotes: 0
Views: 50
Reputation: 23208
Without a minimal compilable verifiable example included in your post this will be limited to general suggestions:
One potential problem is that the prototype:
void array_list_check_and_realloc(array_list_t* array);
Needs to be changed to accommodate a pointer to the object that needs to be given memory:
void array_list_check_and_realloc(array_list_t **array)
This will of coarse also change the way it is called, and the code inside that function.
Some comments on naming:
The struct used includes the member name array
.
The following prototypes also include an argument instance of the entire struct named array
.:
void* array_list_free(array_list_t* array);
void array_list_check_and_realloc(array_list_t* array);
Although legal, this is confusing.
Using the _t
postfix to name your struct array_list_t
is also not recommended for the reasons explained here.
Some comments on your struct construct:
When creating a struct that will be used for linked lists, it is common to include a structure tag, as you have done, but to also include a pointer instance of the struct as a member. This you have not done, but you should consider it.
For example, consider modifying your original struct from this:
typedef struct array_list{
void** array;
size_t size;
size_t capacity;
}array_list_t;
to something more like this: (includes eliminating '_t' postfix from typedef name.)
typedef struct array_list{
size_t size;
size_t capacity;
struct array_list *array //this becomes new nodes of your list.
}ListNode;
Upvotes: 1
Reputation: 50776
Big problem here:
void* array_list_free(array_list_t* array) {
free(array->array);
free(array);
array->capacity = 0; //<<< oups, array points nowhere here as it has been
array->size = 0; // freed on the previous line....
array->array = NULL;
}
remove the three lines starting with array->
from the function.
Upvotes: 1
Reputation: 180113
The problem (at least a problem) is is that array_list_free frees the array_list_t
object itself, not just the internal dynamic array:
free(array);
If that's not a problem in itself (which it is if that object was not dynamically allocated) then it is a problem to continue using that object afterward without allocating new space for it and initializing that space -- both in that function itself and after that function returns.
Speaking of initialization, an initialization function is notable by its absence from those you present. Perhaps you initialize your objects via ordinary initializers or default initialization, or perhaps you just omitted the function, but be aware that you must not rely on uninitialized objects.
Upvotes: 1