【问题标题】:Freeing memory in the caller that is reallocated by the callee?释放被调用者重新分配的调用者内存?
【发布时间】:2014-07-10 17:54:13
【问题描述】:

这是我的情况:

main 根据字符串分配内存,并通过传递地址调用函数。然后该函数适当地调整传递的内存大小以容纳更多数据。之后,当我尝试释放内存时,出现堆错误。

代码如下:

typedef char * string;
typedef string * stringRef;

/**************************
            main
**************************/
int main()
{
    string input = "Mary had";

    string decoded_output = (string)calloc(strlen(input), sizeof(char));
    sprintf(decoded_output, "%s", input);
    gen_binary_string(input, &decoded_output);
    free(decoded_output); /*this causes issue*/

    return 0;
}

void gen_binary_string(string input,stringRef output)
{
    int i=0, t=0;   
    size_t max_chars = strlen(input);   

    /*
        the array has to hold total_chars * 8bits/char.
        e.g. if input is Mary => array size 4*8=32 + 1 (+1 for \0)
    */
    string binary_string = (string)calloc((BINARY_MAX*max_chars) + 1, sizeof(char));

    int offset = 0;

    /* for each character in input string */
    while (*(input+i))
    {       
        /* do some binary stuff... */       
    }

    /* null terminator */
    binary_string[BINARY_MAX*max_chars] = '\0';

    int newLen = strlen(binary_string);
    string new_output = (string) realloc((*output), newLen);
    if (new_output == NULL)
    {
        printf("FATAL: error in realloc!\n");
        free(binary_string);
        return;
    }
    strcpy(new_output, binary_string);

    (*output) = new_output;

    free(binary_string);
}

【问题讨论】:

  • 我建议您使用术语“按地址传递”而不是“按引用传递”。 C++ 对什么是引用有一个特定的概念,由于 C 和 C++ 彼此有些接近,所以不用同一个词来描述 C 概念可以省去您的麻烦。
  • 是的,我解决了我的问题,谢谢!
  • 停止使用指针类型定义,它们使代码难以阅读
  • @zneak 我认为使用“通过引用传递”很好,因为该术语适用于许多语言;虽然你偶尔会遇到那些似乎不愿意承认他们知道你在说什么的超级学究
  • 对不起,McNabb 先生,如果我的问题打扰到您了!!

标签: c memory memory-leaks heap-memory realloc


【解决方案1】:

您可能误解了realloc 的用途。调用realloc 不一定会返回一个新分配的对象。如果可能,它将返回相同的对象,extended 以容纳更多字节。此外,它会自动复制对象的内容。 Theferore: (1) 你不应该复制和 (2) 你不应该释放旧的缓冲区。

realloc()函数改变指向的内存块的大小 到 ptrsize 字节。范围内内容不变 从地区开始到新旧最低 尺寸... (snip) 除非 ptrNULL,否则它一定是由 提前致电malloc()calloc()realloc()。如果该地区 指向已移动,free(ptr) 已完成。


更好地阅读您的代码后,我不明白您为什么在这里使用realloc,因为您没有使用output 的旧内容。如果将realloc 替换为malloc,您将得到相同的行为(和相同的错误)。我认为你真正的问题是你没有分配足够的字节:你应该有strlen(binary_string) + 1 来容纳字符串末尾的'\0'

【讨论】:

  • @nickie,感谢您的解释。这有助于像我这样的新人使用 C 指针。但我正在做 calloc((BINARY_MAX*max_chars) + 1,它应该照顾 '\0'。至少我是这么想的。
  • @KerrekSB 但这会将网站流量减少 90%
  • 不,我的意思是在给realloc 的电话中,你有newLen = strlen(binary_string)。这应该是+1,因为稍后您将使用strcpybinary_string 复制到那里。
【解决方案2】:

更好的选择是从调用者传入char**,让被调用者分配char*,然后在函数末尾传回指针。

这避免了两次分配和一个空闲的需要(总是一个不好的迹象)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 2012-03-05
    • 2019-10-17
    • 1970-01-01
    • 2019-08-18
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多