重新分配后,我们是否会在缓冲区中丢失数据?

33 c memory-management realloc

我很难理解realloc是如何工作的.如果我malloc'ed缓冲区并将数据复制到该缓冲区,让我们说"AB":

 +------------+
 | A | B | \0 |
 +------------+
Run Code Online (Sandbox Code Playgroud)

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

 +------------------------+
 | A | B | \0 | ? | ? | ? |
 +------------------------+
Run Code Online (Sandbox Code Playgroud)

码:

#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);
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 52

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

请注意,realloc如果由于某种原因realloc失败,您的通话将意味着您丢失了数据.这是因为realloc返回失败NULL,但在这种情况下原始内存块仍然有效,但由于你已经覆盖指针,你不能再访问它了NULL.

标准模式是:

newbuffer = realloc(buffer, newsize);
if (newbuffer == NULL)
{
    //handle error
    return ...
}
buffer = newbuffer;
Run Code Online (Sandbox Code Playgroud)

另请注意,malloc在C中不需要转换返回值,也就是说sizeof(char),根据定义,等于1.

  • @ylun的原因在答案中解释 (2认同)

pmg*_*pmg 5

什么都没有丢失.但你真的应该测试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);
}
Run Code Online (Sandbox Code Playgroud)