2

I am trying implement a method that adds a given string to an array that ends with a NULL pointer. This is what I have so far but I am getting an error saying that the pointer being realloc'd was not allocated.

int main(void)
{
    char **strings = init_array();

    strings = add_string(strings, "one");
    strings = add_string(strings, "two");

    return 1;
}


char **init_array(void)
{
    char **array = malloc(sizeof(char *));
    array[0] = NULL;
    return array; 
}


char **add_string(char **array, const char *string)
{
    unsigned int size = 0;
    while (*array) {
        size++;
        array++;
    }

    char **newarr = (char **)realloc(array, sizeof(char *) * (size + 2));

    newarr[size] = malloc(strlen(string)+1);
    strcpy(newarr[size], string);
    newarr[size+1] = NULL;

    return newarr;
}
1
  • OT: unsigned int size = 0; should be size_t size = 0;. Commented Aug 27, 2016 at 20:26

5 Answers 5

2

The issue is array++. You have to pass realloc the same value malloc returned (your array argument), but you modify it during the loop, so it'll work only the first time (because *array will immediately false). You could use:

size_t size;
for(size = 0; array[size]; size++);

And leave the rest untouched.

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

4 Comments

unsigned int size should be size_t size.
@alk Indeed, copypasted and missed. Thank you.
@alk Could you briefly explain the difference?
@MeikVtune: size_t is guaranteed by the C-Standard to be large (small?) enough to address/size all addresses/arrays, which unsigned int isn't (guaranteed to be).
1

In your while (*array) loop you are incrementing not only the size, but also the array pointer itself. As a result, at the end of the loop size contains the length of the array, and the array pointer points to the last (NULL) element. This pointer was never allocated, (it points within an allocated block,) therefore it is not a valid pointer to reallocate. (And definitely that's not what you intended to do.)

So, just don't do array++ within that loop.

Comments

1

Your loop that calculates the number of strings in the array also advances the variable itself. You could use a temporary variable instead:

char **temp = array;
while (*temp)
     ...

Or separate the counting into a function.

BTW you don't need a casting when using realloc, for the same reason you don't do the casting with malloc. This is not a bug, but it better be consistent.

1 Comment

"This is not a bug, but it better be consistent." Also casting malloc() & friends might hide bugs, for example, if the appropriate prototype was not given.
1

Summarizing all other answers given so far, adding some best practise tweaks, the relevant code should look like this:

char **add_string(char **array, const char *string)
{
  char ** newarr;
  size_t size = 0;

  assert (NULL != string); /* Need to include assert.h */

  if (NULL != array)
  {
    while (NULL != array[size]) 
    {
      ++size; /* Just count, do not touch the pointer value allocated. */
    }
  }

  newarr = realloc(array, (size + 2) * sizeof *newarr);
  if (NULL == newarr) /* Test the outcome of reallocation. */
  {
    perror("realloc() failed"); /* Need to include stdio.h */
    return NULL;
  }

  newarr[size] = malloc(strlen(string) + 1);
  if (NULL == newarr[size])
  {
    perror("malloc() failed"); /* Need to include stdio.h */
    /* Might want to clean up here and indicate the failure to the 
       caller by returning NULL. */
  }
  else
  { 
    strcpy(newarr[size], string);  
  }

  newarr[size+1] = NULL;

  return newarr;
}

Or even tighter:

char **add_string(char **array, const char *string)
{
  assert (NULL != string); /* Need to include assert.h */

  {
    size_t size = 0;

    if (NULL != array)
    {
      while (NULL != array[size]) 
      {
        ++size; /* Just count, do not touch the pointer value allocated. */
      }
    }

    {
      char ** newarr = realloc(array, (size + 2) * sizeof *newarr);
      if (NULL == newarr)
      {
        perror("realloc() failed"); /* Need to include stdio.h */
      }

      if (NULL != newarr)
      {  
        newarr[size] = malloc(strlen(string) + 1);
        if (NULL == newarr[size])
        {
          perror("malloc() failed"); /* Need to include stdio.h */
        }
        else
        { 
          strcpy(newarr[size], string);  
        }

        newarr[size+1] = NULL;
      }

      return newarr;
    }
  }
}

2 Comments

Your while (array && *array) loop is wrong. My suggestion to not do array++ in the loop should not be read literally, of course. You must somehow look at every character in the array, you can't do that if you are only looking at the first (0th) character.
@MikeNakis: Although it's not about "looking into characters", you very well correct that the while-loop was incomplete. Thanks for reminding me not to answer questions on SO in the middle of the night. ;-) Fixed now.
0

The easiest way would be to preserve initial array pointer and use it to realloc memory.

int main(void)
{
    char **strings = init_array();

    strings = add_string(strings, "one");
    strings = add_string(strings, "two");

    return 1;
}


char **init_array(void)
{
    char **array = malloc(sizeof(char *));
    array[0] = NULL;
    return array; 
}


char **add_string(char **array, const char *string)
{
    char** cache = array;
    unsigned int size = 0;
    while (*array) {
        size++;
        array++;
    }

    char **newarr = (char **)realloc(cache, sizeof(char *) * (size + 2));

    newarr[size] = malloc(strlen(string)+1);
    strcpy(newarr[size], string);
    newarr[size+1] = NULL;

    return newarr;
}

Another note - main function should return 0 on success.

1 Comment

1. Do not cast void-pointer (as for example returned by realloc()) in C; 2. The call to realloc() misses appropriate error checking.

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.