以下是我的情况:
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);
}
答案 0 :(得分:3)
您可能误解了realloc
的目的。调用realloc
不一定会返回新分配的对象。如果可能,它将返回相同的对象扩展以保存更多字节。此外,它会自动复制对象的内容。 Theferore:(1)你不应该复制和(2)你不应该释放旧的缓冲区。
realloc()
函数会更改指向的内存块的大小 到ptr
到size
个字节。内容将在该范围内保持不变 从该地区的起点到最新的新旧 尺寸... (剪辑)除非ptr
为NULL
,否则必须由 之前致电malloc()
,calloc()
或realloc()
。如果该地区 指向被移动,free(ptr)
已完成。
在更好地阅读您的代码后,我不明白为什么您在这里使用realloc
,因为您没有使用{{1}的旧内容}。如果您将output
替换为realloc
,您将获得相同的行为(以及相同的错误)。我认为你真正的问题是你没有分配足够的字节:你应该malloc
来容纳字符串末尾的strlen(binary_string) + 1
。
答案 1 :(得分:1)
更好的选择是从调用者传入char**
,让被调用者分配char*
,然后在函数末尾传回指针。
这可以防止需要两次分配和一次免费(总是一个坏的标志)。