【问题标题】:In C, free half of the memory chunk, without freeing the other half在 C 中,释放一半的内存块,而不释放另一半
【发布时间】:2015-07-23 10:34:03
【问题描述】:

如果我分配了一个内存块说

char *a =(char*)malloc(sizeof(char)*10);   

我愿意

strcpy( "string of len 5",a);   

那么有没有办法释放我剩余的部分内存块?
在其他情况下,如果我这样做

strcpy("string of len5", (a+5));

那么前半部分将是空的。有没有办法free()第一部分而不释放后半部分?

请不要建议realloc(),因为它会在那里分配一块新的内存复制内容并释放之前的内容。(AKAIK)。

【问题讨论】:

  • “请不要推荐realloc()”——你应该使用realloc()
  • realloc() 有什么问题吗?
  • 如果“不建议 realloc”的原因是因为该指针有多个别名副本浮动,可能会因调用 realloc 而无效 - 好吧,不要保留指针的多个别名副本。编程需要纪律。祝你好运。
  • BTW sizeof(char) 是多余的,标准保证为1。

标签: c malloc free


【解决方案1】:

不,你没有办法free()一半部分动态分配的内存。您需要一次全部free()

在通过动态内存分配获取内存时,你基本上得到了一个指针。您需要将 exact 指针传递给free()。传递一个指向free() 的指针,它不是由malloc() 或家庭返回的,是undefined behaviour

仅供参考,请参阅related answer

【讨论】:

    【解决方案2】:

    realloc() 不需要复制,good 实现可以避免不必要的复制。你真的应该依赖它。 (澄清一下:出于性能原因,当然。始终假设实现可能复制)

    #include <stdlib.h>
    #include <stdio.h>
    
    int main()
    {
        void *test1 = malloc(16);
        void *test2 = realloc(test1, 8);
        free(test2);
    
        printf("malloc: %x -- realloc: %x\n", test1, test2);
        return 0;
    }
    

    示例输出:

    malloc: 4779c0 -- realloc: 4779c0

    【讨论】:

      【解决方案3】:

      malloc(3) API 不允许这样做,realloc(3) 除外。在常见的实现中,使用 realloc 收缩(通常?)不会触发副本,尤其是。如果缓冲区很大,则不会。

      如果您真的希望能够保证不复制,请在 POSIX mmap(2) / munmap(2) 之上实现您自己的分配器。您可以取消映射部分映射,而不会影响不在给定地址范围内的页面。

      【讨论】:

        【解决方案4】:

        如果不使用 realloc,就不可能在 C 标准的框架中完成任务。使用 realloc 没有什么复杂的。

        这是一个演示程序,展示了它是如何完成的

        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        #define HELLO_WORLD "Hello World"
        
        int main( void )
        {
            char *s;
            size_t n = sizeof( HELLO_WORLD );
        
            s = malloc( n );
        
            strcpy( s, HELLO_WORLD );
        
            puts( s );
        
            memmove( s, s + 6, n - 6 ); 
        
            puts( s );
        
            char *t = realloc( s, n - 6 );
        
            if ( t ) s = t;
        
            puts( s );
        
            free( s );
        }
        

        程序输出是

        Hello World
        World
        World
        

        另一种方法是简单地将子字符串复制到另一个分配的字符串中。例如

        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        #define HELLO_WORLD "Hello World"
        
        int main( void )
        {
            char *s;
            size_t n = sizeof( HELLO_WORLD );
        
            s = malloc( n );
        
            strcpy( s, HELLO_WORLD );
        
            puts( s );
        
            do
            {
                char *t = malloc( n - 6 );
        
                if ( t )
                {
                    strcpy( t, s + 6 );
                    free( s );
                    s = t;
                }
            } while( 0 );        
        
            puts( s );
        
            free( s );
        }
        

        程序输出是

        Hello World
        World
        

        【讨论】:

          【解决方案5】:

          你没有办法这样做,有没有必要释放一半?这根本不安全。动态分配的内存必须全部释放。

          【讨论】:

            【解决方案6】:

            当成功地从程序的 HEAP 内存空间返回一个逻辑上连续的内存块时调用 malloc,比您请求的多一点。

            这个额外的内存用于存储信息,例如分配块的大小,以及到块链中下一个空闲/使用块的链接。

            当您释放指针时,它会使用该地址来查找它添加到已分配块的开头(通常)的特殊信息。

            因此,您释放的内存不能少于使用 malloc 分配的内存。如果您传递不同的地址,它将给出未定义的行为。

            为此使用了realloc

            【讨论】:

              猜你喜欢
              • 2020-09-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-11-27
              • 1970-01-01
              • 2016-05-07
              • 1970-01-01
              • 2010-09-26
              相关资源
              最近更新 更多