释放被调用者重新分配的调用者的内存?

时间:2014-05-21 21:33:20

标签: c memory memory-leaks heap realloc

以下是我的情况:

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);
}

2 个答案:

答案 0 :(得分:3)

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

  

realloc()函数会更改指向的内存块的大小   到ptrsize个字节。内容将在该范围内保持不变   从该地区的起点到最新的新旧   尺寸... (剪辑)除非ptrNULL,否则必须由   之前致电malloc()calloc()realloc()。如果该地区   指向被移动,free(ptr)已完成。


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

答案 1 :(得分:1)

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

这可以防止需要两次分配和一次免费(总是一个坏的标志)。