Search code examples
cstringsizerealloc

Realloc - Realloc do not make smaller char*


  OS: Linux
  CC: GCC 4.8.2

Targer: Change size of char* -> to smaller

PROBLEM: Size after change is same...

line is string with data...

Code fragment:

 char * tmp = NULL;

[...]

 tmp = malloc(sizeof(char) * 8);

 strncpy(tmp, line, sizeof(char) * 8);

[...]

Now smaller tmp:

 printfTest(tmp); //Content dump

 nevAddr = realloc(tmp, sizeof(char) * 3);

 if(newAddr != NULL)
 {
    tmp = newAddr;
 }
 else
 {
     free(tmp);
     puts("Realloc - FAIL");
     exit(VALID);
 }

 printfTest(tmp); //Content dump

printfTest function:

  void printfTest(char * data)
  {
      printf("Test: '%s'", tmp);
  }

Result:

 Test: 'BLABLABL' //8chars
 Test: 'BLABLABL' //8chars (!? Why)

Where is my fail?


Solution

  • You are confusing two different concepts of "size". Here's a character array with 100 chars:

    char x[100]; // sizeof(x) / sizeof(x[0]) == 100
    strcpy(x, "short string");
    

    The size of the x array is still 100, even though the length of the string, strlen(x) is just 12.

    (Actually, maybe you could benefit from a basic introduction to strings in C, like this tutorial instead of reading this answer. )

    When you print a string in C, the software keeps printing characters until it finds a \0 (the null character), even if this involves reading pass the end of the array. In fact, the compiler cannot know if it has gone past the array. It just blindly continues until the finds the null character.

    The strcpy above actually writes 13 bytes, not 12. It prints the 12 characters and the null character on the end.

    This means that an array in C that is intended to hold a string must actually have one extra space to hold the null character. If you want to store "world", you must have at least six characters

    char y[5];
    strcpy(y,"hello"); // undefined behaviour, as y is too small
    char z[6];
    strcpy(z,"hello"); // OK
    

    (And no, strncpy does not fix this problem. "No null-character is implicitly appended at the end of destination if source is longer than num. ")

    Anyway, to return to your question. One way to shorten the string would be to write a null character in the appropriate place:

    char x[100];
    strcpy(x, "hello");
    printf("%s\n", x); // prints "hello"
    x[3] = '\0'; // replace the second 'l' with the null
    printf("%s\n", x); // prints "hel"
    

    To change the string, you need to change the bytes, perhaps with code like mine, or perhaps with another strcpy.

    Simply calling realloc does not actually change any of the bytes in the string, it merely frees some of the memory nearby.