Can I free only a part of a string?

1k views Asked by At

I am filling up a string of characters and I double its size from time to time.

When I finish, I would like to free unused memory.

void fun (char **str, size_t *len) {
  size_t lsi; //last_significant_index
  //filling up the str and reallocating from time to time.
  //*len is storing the total size of allocated memory at this point
  
  // idea #1
  free((*str)[lsi + 1]); 

  // idea #2
  for(size_t i = lsi + 1; i < *len; i++) {
    free(&(*str)[i]);
  }
}

None of these ideas seem to work however

Is it even possible to do it? If so, how?


Details:

I am using this function to reallocate my strings:

static void increase_list_size(char **list, size_t *list_len)
{
   size_t new_list_size = (*list_len + 1) * 2; // I am not allocating my list at the declaration, so *list_len initially equals 0.
   char *new_list = malloc(sizeof(char) * new_list_size);
   for (size_t i = 0; i < *list_len; i++)
   {
       new_list[i] = (*list)[i];
   }
   if (list != NULL) // I don't want to free an empty list (it wasn't allocated at the declaration!
   {
       free(*list);
   }
   (*list) = new_list;
   *list_len = new_list_size;
}

As you can see, I am allocating two-times more memory every time - that's why I wanted to free unused memory at the end.

I thought there was some kind of a tricky way to do it, since I felt that you can only use free() to free whole memory block.

4

There are 4 answers

1
fferri On BEST ANSWER

No, you can only free() pointers that have been returned by malloc().

You want to use realloc() to change the allocated memory size to a smaller (as well as larger) size. The contents of the array will be preserved.

Example:

#include <stdlib.h>
int main() {
    char *str = malloc(100);
    ...
    str = realloc(str, 50);
    ...
    free(str);
}

Remember to check the return value of realloc() (as well as the one of malloc()) to ensure that the (re)allocation has not failed.

0
Vlad from Moscow On

You can use standard C function realloc declared in header <stdlib.h>

For example

char *s = malloc( 100 );
strcpy( s, "Hello world" );

char *p = realloc( s, strlen( s ) + 1 );

if ( p != NULL ) s = p;

Here is a demonstrative program

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
    char *s = malloc( 100 );
    strcpy( s, "Hello world" );

    char *p = realloc( s, strlen( s ) + 1 );

    if ( p != NULL ) s = p; 

    puts( s );

    free( s );

    return 0;
} 

The program output is

Hello world

Or if you want to write a separate function then it can look the following way

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void resize( char **s, size_t n )
{
    char *p = realloc( *s, n );

    if ( p != NULL ) *s = p;
}   

int main( void )
{
    char *s = malloc( 100 );
    strcpy( s, "Hello world" );

    resize( &s, strlen( s ) + 1 );

    puts( s );

    free( s );

    return 0;
} 

Also you can use POSIX function strdup

0
hobbs On

You can only free a pointer that is the result of malloc or realloc. You can't reduce the size of an allocation by freeing at an arbitrary offset from it. But you can realloc it to a smaller size: realloc(*str, lsi).

0
Deepak On

one way is to create a new string and use only space required and copy the content to this one. now you can free the previous one. I will use this is realloc() is not allowed (sometimes in homework)

the other way is realloc() as others suggested.