我可以只释放字符串的一部分吗?

Can I free only a part of a string?

我正在填充一串字符,并且不时将其大小加倍。

完成后,我想释放未使用的内存。

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 这些想法似乎可行

甚至可以做到吗?如果是,怎么做?


详情:

我正在使用这个函数重新分配我的字符串:

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;
}

如您所见,我每次都分配两倍的内存 - 这就是为什么我想在最后释放未使用的内存。

我认为有某种 tricky 的方法可以做到这一点,因为我觉得你只能使用 free() 来释放整个内存块。

不,您只能 free() 已被 malloc() 编辑过的指针 return。

您想使用 realloc() 将分配的内存大小更改为更小(以及更大)的大小。数组的内容将被保留。

示例:

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

记得检查 realloc() 的 return 值(以及 malloc() 的值)以确保(重新)分配没有失败。

您可以使用在 header <stdlib.h>

中声明的标准 C 函数 realloc

例如

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

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

if ( p != NULL ) s = p;

这是一个演示程序

#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;
} 

程序输出为

Hello world

或者如果你想写一个单独的函数,那么它可以像下面这样

#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;
} 

也可以使用POSIX函数strdup

您只能 free 作为 mallocrealloc 结果的指针。您不能通过 free 以任意偏移量减少分配的大小。但是您 可以 realloc 将其缩小:realloc(*str, lsi).

一种方法是创建一个新字符串并仅使用 space 所需的内容并将内容复制到此字符串中。现在你可以释放前一个。 我将使用这是不允许的 realloc() (有时在作业中)

另一种方法是其他人建议的 realloc()。