'Dynamic array of structs in C using realloc
I'm trying to create a simple dynamic array of structures, but I'm unsure about how to go about doing it.
I have
n = 1;
typedef struct {
char wordName [50];
int counter;
}Words;
Words * array;
And now I want to reallocate it in this loop.
if(strlen(token) > 6){
array = (Words*)realloc(array, sizeof(Words)*n++);
strcpy(array->wordName, token);
//printf("%s ", array->wordName);
array++;
}
I can add data to the structure, it prints it all out in a loop just fine. But when I add array++, I get:
realloc(): invalid pointer
Am I accessing the data incorrectly? Or do I not even have any more pointers beyond the head?
Solution 1:[1]
array++; causes array to advance by sizeof (a_pointer) so it now no longer points to address first returned by realloc(). That means any future attempt to realloc() with the new address of array will result in the error "Invalid pointer, pointer was not initially allocated with call to malloc, calloc or realloc".
Further, if array is not initialized NULL, then you cannot use realloc() for the initial allocation. Initializing n = 1; mixes a count with and index. Always keep the count so it is the next index to be filled. For 0 you can use an if / else or ternary, e.g.
n = 0;
...
if (n) { /* if n > 0 (not 1st allocation, use realloc) */
/* always realloc using a temporary pointer */
void *tmp = realloc (array, (n + 1) * sizeof *array);
if (!tmp) { /* validate EVERY allocation */
/* handle error, return */
}
array = tmp; /* assign reallocated block to array */
n += 1; /* increment count */
}
else { /* initial allocation */
array = malloc (sizeof *array);
if (!array) { /* validate EVERY allocation */
/* handle error, return */
}
n += 1; /* increment count */
}
/* rest of your strcpy here
* VALIDATE strlen(token) > 0 AND < 50
*/
/* note: you can consolidate both n += 1; here. duplicated for clarity */
You always call realloc() with a temporary pointer because when (not if) realloc() fails it returns NULL which will overwrite the address pointing to the allocated block of memory creating a memory leak. e.g. never do:
pointer = realloc (pointer, size);
Instead, by using a temporary pointer, if realloc() fails, pointer (your array) will still point to the last allocated and still valid block of memory allowing you to use what is stored there AND allowing you to free() that block of memory when you are done with it.
Note, you can use a ternary, but it is much less readable:
Words *array = NULL;
size_t n = 0;
...
void *tmp = realloc (array, sizeof *array * n ? n + 1 : 1);
if (!tmp) { /* validate EVERY allocation */
/* handle error, return */
}
array = tmp;
n += 1;
/* rest of your strcpy here
* VALIDATE strlen(token) > 0 AND < 50
*/
In C, there is no need to cast the return of malloc (or calloc or realloc), it is unnecessary. See: Do I cast the result of malloc?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
