c - 如果 Realloc() 失败,调用者是否会丢失前一个 malloc() 调用中的数据?

标签 c memory malloc glibc realloc

以下是考试引述(1% 顶尖大学)。

我失败了,因为我的答案与“批准”的答案不同。

我有一种预感,他的(教授,著名的 C 专家)答案是不正确的。

以下是“批准”答案后的问题。

There is a potential bug in the following function. What is it and how would I fix it?

Hint: this has something to do with the use of the realloc() function. Please identify the line numbers you would change and what you would replace them with.

BOOLEAN lengthen_string(char* string, const char newcontents[])
{
        int newlen = strlen(string) + strlen(newcontents) + 1;
        string = realloc(string, newlen);

        if (!string) {
                perror("malloc");
                return FALSE;
        }

        strcat(string, newcontents);
        return TRUE;
}

教授提供的“正确”答案是:

line 4: realloc returns a NULL pointer when it fails to allocate. This means that on failure the original data is lost.

To fix this, assign the result of realloc to a temporary variable and test that first.

Ie: line 4:

char * temp=realloc(string, newlen);
if(!temp) ... (all remains the same)

after old line 9, string = temp;

有什么想法吗?

顺便说一句,我的回答是@string是一个局部变量,函数的原型(prototype)应该是char **string,这里调用者传递一个指向它的字符串指针,然后被调用者会将任何 realloc() 返回值分配给 *string

有什么想法吗?

最佳答案

你们都是对的。

教授是正确的,因为 realloc() 不会在失败时改变传入的内存,从而使输入的 string 指针完好无损,但是如果 NULL失败的返回值立即分配给 string 然后原始数据丢失和泄漏。因此,在将新指针值分配给 string 之前,需要首先检查是否存在故障。

你是对的,因为 string 需要通过指针传递,因此如果 realloc() 返回不同的内存地址,它可以重新分配一个新值。

正确的解决方案应该是这样的:

BOOLEAN lengthen_string(char** string, const char newcontents[])
{
    if (!string)
    {
        errno = EINVAL;
        perror("bad input");
        return FALSE;
    }
    size_t newsize = strlen(*string) + strlen(newcontents) + 1;
    char *temp = realloc(*string, newsize);
    if (!temp)
    {
        perror("realloc failed");
        return FALSE;
    }
    strcat(temp, newcontents);
    *string = temp;
    return TRUE;
}

或者,还有一些优化空间,eg:

BOOLEAN lengthen_string(char** string, const char newcontents[])
{
    if (!string)
    {
        errno = EINVAL;
        perror("bad input");
        return FALSE;
    }
    char *temp;
    if (!*string)
    {
        temp = strdup(newcontents);
        if (!temp)
        {
            perror("strdup failed");
            return FALSE;
        }
    }
    else
    {
        size_t offset = strlen(*string);
        size_t size = strlen(newcontents) + 1;
        temp = realloc(*string, offset + size);
        if (!temp)
        {
            perror("realloc failed");
            return FALSE;
        }
        memcpy(temp + offset, newcontents, size);
    }
    *string = temp;
    return TRUE;
}

关于c - 如果 Realloc() 失败,调用者是否会丢失前一个 malloc() 调用中的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61967608/

相关文章:

c - 有没有办法找出在 c 中使用 malloc 时可用的最大字节数?

php - 将数据库保存在内存中,即使客户端脚本断开连接

c - 在 C 中处理包含多个 Null 字符的字符串

c++ - 动态内存分配的限制

c++ - 在 C++20 之前将 malloc 用于 int 未定义行为

c - 我应该从代表人力资源管理系统中员工的抽象数据类型中抽象出数据库 API 吗?

c - 在系统调用和命令提示符中调用 'cd' 的区别

c - 组播/UDP 路由器

c - 为什么整数在溢出时会有不同的行为

c - 多线程 C 应用程序应如何处理失败的 malloc()?