2

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?

3
  • Try ++n which will give you the incremented value of n. Commented Mar 10, 2022 at 3:31
  • This is all the important code? Is the realloc the only place where you allocate memory? Your variable array is uninitialized, which might explain the "invalid pointer" message. You must initialize it to NULL. Commented Mar 10, 2022 at 3:41
  • array is a special pointer returned by realloc. If you want realloc again, you need pass old array value without change. Something like b = realloc(a, size1); c = realloc(b, size2);. You can not do b = realloc(a, size1); b++; c=realloc(b, size2);. Maybe you can make a backup first, like b=realloc(a, size1); b_tmp=b++; c=realloc(b_tmp, size2);. Commented Mar 10, 2022 at 3:41

1 Answer 1

4

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?

Sign up to request clarification or add additional context in comments.

4 Comments

always realloc using a temporary pointer was looking for this +1!
I guess I should expand on that in the answer. Thanks.
Why even consider a ?:? Instead of sizeof *array * n ? n + 1 : 1, why not sizeof *array * (n + 1)?
@chux-ReinstateMonica - always one step ahead, quite true. n + 1 will do without the ternary at all. I suspect the stuck code-pattern in my thought process involved a postscript n++. But not needed with the explicit addition. (thwack... light-bulb winks on :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.