I am trying to implement a dynamic List in C and I do not get why I get the "Stack around the variable 'memory' was corrupted." Error when I am trying to add a second Item to the list.
struct LIST {
unsigned int size;
unsigned int count;
void** items;
};
struct LIST* list_init(unsigned int size)
{
struct LIST* createList = (struct LIST*)calloc(1, sizeof(struct LIST));
void* memory = calloc(size, sizeof(void*));
if (memory == 0 || createList == 0) return 0;
createList->items = &memory;
createList->size = size;
return createList;
}
void list_add(struct LIST* list, void* item)
{
if (list->count + 1 > list->size)
{
void* memory = realloc(list->items, (sizeof(void*)) * list->count + 1);
list->items = &memory;
return;
}
else
{
list->items[list->count] = item;
list->count = list->count + 1;
}
}
int main()
{
const char* str = "Hello";
struct LIST* list = list_init(2);
list_add(list, (void*)str);
list_add(list, (void*)str);
list_add(list, (void*)str);
list_add(list, (void*)str);
printf("Items in List: %d \n\n", list_count(list));
list_clear(list);
free(list);
return 0;
}
The code never goes into the if block that could do anything with the memory variable, however in the second list_add Call it crashes when exiting the function (Note I am using the VS2022 Debugger to step through it).
I expect to have 2 items added to the list before realloc is used to extend the list by one.
A few issues ...
LIST,itemsshould be justvoid *and notvoid **list_add,memoryis a stack local variable that goes out of scope. Changelist->items = &memorytolist->items = memorylist->count + 1in therealloc. We want to incrementlist->sizeinstead and use that in the call.elseblock) should be executed unconditionallyvoid *pointerchar *arrays), we need to duplicate the string when storing. So, we should usestrdupstrdup, just doingfree(list)at the end is insufficient. We need to loop through all elements and free the strings we duplicated inlist_add.list_initis replicating code inlist_add. It should just do the firstcalloconly.list_add(e.g.list_add(list,"Hello");, the 2nd arg should haveconst.Here is the refactored code. It is annotated with the bugs and fixes:
In the code above, I've used
cppconditionals to denote old vs. new code:Note: this can be cleaned up by running the file through
unifdef -kHere is the program output:
Here is the cleaned up code: