【问题标题】:Do we lose data in a buffer after realloc'ing?重新分配后我们会丢失缓冲区中的数据吗?
【发布时间】:2012-02-26 21:45:13
【问题描述】:

我无法理解 realloc 的工作原理。如果我 malloc'ed 一个缓冲区并将数据复制到该缓冲区,假设是“AB”:

 +------------+
 | A | B | \0 |
 +------------+

然后我重新分配了缓冲区,数据中是否会丢失任何内容(甚至是单个字节)?或者它只是扩展缓冲区? :

 +------------------------+
 | A | B | \0 | ? | ? | ? |
 +------------------------+

代码:

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

int main(void){

    char* buffer    = (char*) malloc( sizeof(char) * 3 );
    strncpy(buffer, "AB", 2);

    buffer          = (char*) realloc(buffer, sizeof(char) * 6); /* Will there be any lost here? */
    free(buffer);
    return(0);
}

【问题讨论】:

    标签: c memory-management realloc


    【解决方案1】:

    增加块大小的realloc 将保留原始内存块的内容。即使内存块无法在放置时调整大小,旧数据也会被复制到新块中。对于减小块大小的realloc,旧数据将被截断。

    请注意,如果由于某种原因realloc 失败,您对realloc 的调用将意味着您丢失数据。这是因为realloc 失败并返回NULL,但在这种情况下,原始内存块仍然有效,但您无法再访问它,因为您已经覆盖了指向NULL 的指针。

    标准模式是:

    newbuffer = realloc(buffer, newsize);
    if (newbuffer == NULL)
    {
        //handle error
        return ...
    }
    buffer = newbuffer;
    

    另请注意,在 C 中不需要从 malloc 转换返回值,并且根据定义,sizeof(char) 等于 1

    【讨论】:

    • 你为什么不能buffer = realloc(buffer, newsize);
    • @ylun 原因在答案中解释
    • 对了,所以为了防止数据丢失,你先检查分配是否成功,然后重新分配,谢谢。
    • 如果你重新分配一个较小的内存块会怎样?
    • 显然你失去了你释放的东西,但你保留了其余的
    【解决方案2】:

    什么都没有丢失。但是你真的应该测试realloc()(和之前的malloc())是否“有效”。
    此外,对 malloc 的返回值的强制转换充其量是多余的,它可能会隐藏编译器在没有它的情况下会捕获的错误。

    基于您想要字符串的假设,您对 strncpy 的使用是错误的

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void) {
        char *buffer = malloc(3);
        if (buffer == NULL) /* no memory */ exit(EXIT_FAILURE);
    
        strncpy(buffer, "AB", 2);
        /* ATTENTTION! ATTENTION: your array is not a string.
        ** buffer[2] is not the zero string terminator */
    
        // buffer = realloc(buffer, 6); /* Will there be any lost here? */
        /* If realloc returns NULL, you've just lost the only pointer to
        ** the allocalted memory, by overwriting it with NULL.
        ** Always `realloc` to a temporary variable */
        char *tmp_buffer = realloc(buffer, 6);
        if (tmp_buffer == NULL) {
            /* realloc failed */
        } else {
            /* realloc worked, no bytes lost */
            buffer = tmp_buffer;
            /* ATTENTION! ATTENTION: buffer is still not a string
            ** buffer[0] is 'A', buffer[1] is 'B',
            ** all other elements of buffer are indeterminate */
        }
    
        free(buffer);
        return(0);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多