4

I'm trying to build a dynamically grown array of strings. Neither the number of strings nor the length of each string is known at compile time. Here's the code I came up with so far (this is just me playing with the syntax):

char **result = NULL;
char *temp = NULL;
result = (char **)realloc (result,sizeof(char *) * 1);
temp= (char *)realloc(temp,5 * sizeof(char));

strcat(temp,"hello");


temp= (char *)realloc(temp,10 * sizeof(char));

strcat(temp," world");

printf ("%s \n", temp);
result[0]=temp;
free(temp);
printf ("%s \n", result[0]);

result = (char **)realloc (result, sizeof(char *) * 2);
temp= (char *)realloc(temp,10 * sizeof(char));
strcat(temp,"0123456789");

temp= (char *)realloc(temp,15 * sizeof(char));
strcat(temp,"asdfg");

printf ("%s \n", temp);
result[1]=temp;
free(temp);
printf ("%s \n", result[0]);
printf ("%s \n", result[1]);)

Now, when I print result[0] or result[1], its just an empty string, why doesn't result[1]=temp; work?

Here's what I tried earlier, but it didn't work, I kept getting "invalid size" errors when using realloc() on that last line:

char **result = NULL;
result = (char **)realloc (result,sizeof(char *) * 1);
result[0]= (char *)realloc(result[0],5 * sizeof(char));

strcat(result[0],"hello");
printf ("%s \n", result[0]);

result[0]= (char *)realloc(result[0],10 * sizeof(char));

strcat(result[0]," world");
printf ("%s \n", result[0]);

result = (char **)realloc (result, sizeof(char *) * 2);
result[1]= (char *)realloc(result[1],10 * sizeof(char));
strcat(result[0],"0123456789");

result[0]= (char *)realloc(result[1],15 * sizeof(char));
strcat(result[0],"asdfg");

If anybody could help me get either version working, I would be very grateful.

UPDATE: Ok, I got both versions of the code working. Now when I try to use this same format in my actual program, I get errors such as

*** glibc detected *** ./uvicfmt3: realloc(): invalid next size: 0x08ed3170 ***

Now in my program, the "result" is declared as a global variable (using the second version of my code), and the realloc functions are called in different subroutines. Is that what's causing the problem? How could I get around this?

3
  • The only function for the casts is code obfuscation. Make sure you have #include <stdlib.h> and get rid of the casts. If you're compiling with a C++ compiler, try to write C++ in the 1st place ;) Commented Nov 30, 2011 at 15:01
  • that error realloc(): invalid next size - really, any error from *alloc besides "out of memory" - is a sign. It means you've probably corrupted the heap, overwriting the data structures that *alloc uses to keep track of the location and size of free blocks. When you see that error, start looking for invalid array writes, double frees, and stuff like that. Commented Nov 30, 2011 at 16:30
  • "hello" takes 6 bytes (5 for hello + 1 for terminating ASCII NUL), "hello world" takes 12 bytes. Commented Nov 30, 2011 at 19:00

2 Answers 2

2

The following statement makes both result[0] and temp point to the same memory address:

result[0]=temp;

Having performed the above assignment, you then free(temp) and try to access result[0]:

free(temp);
printf ("%s \n", result[0]);

This is undefined behaviour, since you're accessing the memory that's just been deallocated.

The same goes for the identical code you have for result[1].

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

Comments

2
  • In the first example you are using a string after freeing it
  • In the second example you are strcating to unallocated memory (plus the uneducated realloc(result[0] makes no sense)

You could try this:

char **result = NULL;
result = realloc(result, sizeof(char *) * 1);

result[0] = strdup("hello");

/* ... */

result = realloc(result, sizeof(char *) * 2);
result[1] = strdup(" world");

Now strdup isn't standard but it's not hard to steal it / fake it. Here's one attempt:

char *strdup2(const char *str)
{
    size_t len;
    char *rval = NULL;

    len = strlen(str);        /* We should probably check this. */
    rval = malloc(len + 1);   /* And this. */

    memcpy(rval, str, len);
    rval[len] = 0;

    return rval;
}

EDIT

I was under the (possibly wrong) impression you want to later modify the strings. If that is not the case, simply storing them (without strdup) is adequate:

result[0] = "hello";

2 Comments

Could you please explain why strdup is necessary in this case?
@user1073407 It's only necessary if you plan to modify the strings. Otherwise it's perfectly legitimate to simply store the literals.

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.