Search code examples
cstringmallocfree

C: How to free the initial section of an allocated string?


How can I free a string up to a certain point? For example if I have:

char *s = (char *)malloc(sizeof(char) * 21);
s[20] = '\0';
int i = 0;
while (i < 21)
{
    s[i] = i + 'a';
    i++;
}

And then I cut off the string at some point and store that half:

*(s + 10) = '\0';
char *m = s + 11;

Is there a way to free s up to s + 10 or the first \0?


Solution

  • Since s has been allocated by the system, you can perform a realloc on it to shorten the size:

    s = realloc(s, 11);
    

    But you cannot free the start of an allocated zone without freeing the rest, that you cannot. Use memmove & realloc to shift the data and reduce size afterwards.

    Attempting to free a pointer which hasn't been allocated, or an allocated pointer plus an offset results in undefined behaviour.

    You could do (as you suggested yourself, but with problems fixed :)):

    char *c = strdup(s + 10);
    free(s);
    s = c;
    

    so now s points to the end of the string.

    alternative without strdup but using standard functions only (with the risk of forgetting the null-termination char):

    char *c = malloc(strlen(s) - 10 + 1);
    strcpy(c,s + 10);
    free(s);
    s = c;
    

    and the memmove solution I was hinting about at first (avoids to allocate/free but offset/size is trickier to compute):

    int offset = 10;
    int size = strlen(s) - offset;
    memmove(s,s+offset,size);
    s[size]='\0';  // null-terminate
    s = realloc(s,size+1);  // adjust size after null-termination