我的程序中有两个struct
。第一个huffchar
在下面,仅显示了一般结构(大部分与问题无关),但是第二个huffcoder
是我遇到的问题:>
struct huffchar {
int freq;
int is_compound;
int seqno;
union {
struct {
struct huffchar * left;
struct huffchar * right;
} compound;
unsigned char c;
} u;
};
struct huffcoder {
int freqs[NUM_CHARS];
int code_lengths[NUM_CHARS];
unsigned long long codes[NUM_CHARS];
struct huffchar * tree;
int sizeOfTree;
};
当我在程序中初始化huffcoder
时,我将ourHuffCoder
的大小分配给huffcoder
,然后将用于X个元素的内存分配给struct huffchar * tree
:< / p>
struct huffcoder * ourHuffChar = malloc(sizeof(struct huffcoder));
ourHuffChar -> tree = malloc(sizeof(struct huffchar)*NUM_CHARS);
但是,我稍后需要将这棵树变大,并且不知道最后这棵树上将有多少个元素。换句话说,每次添加元素时,我都会使用realloc()
创建一个新树,该树大一个元素,然后将tree
中huffcoder
的指针设置为此新的{ {1}}。
以下几行代码旨在实现这一目标:
updatedTree
请注意,在将 struct huffchar * updatedTree = realloc(ourHuffCoder -> tree, (ourHuffCoder->sizeOfTree+1)*sizeof(struct huffchar));
free(ourHuffCoder -> tree);
ourHuffCoder -> tree = updatedTree;
指针更新为free(ourHuffCoder -> tree)
之前,我使用行tree
释放了先前分配给树的内存。但是,当我到达updatedTree
行时,分配给HuffCoder指针free(ourHuffCoder -> tree)
的 entirety 的内存将被释放,而不仅仅是分配给ourHuffCoder
的内存。
这是在之后运行free(ourHuffCoder->tree)
行:
我也尝试创建一个全新的指针free(ourHuffCoder->tree)
,并将此变量用于huffchar * ourTree = ourHuffCoder -> tree
方法,但得到的结果相同。
为了测试我的代码,我修改了上面的代码以删除free()
行,
free()
这显然不是我应该做的,因为我很快就会用光内存,但是我想看看是否将 struct huffchar * updatedTree = realloc(ourHuffCoder -> tree, (ourHuffCoder->sizeOfTree+1)*sizeof(struct huffchar));
ourHuffCoder -> tree = updatedTree;
中指向tree
的指针更新为指向{{1 }},其中包括:
我的问题是,为什么要释放分配给整个ourHuffCoder -> tree = updatedTree;
结构的内存,而不是仅仅释放给ourHuffCoder -> tree = updatedTree;
的内存?我该如何解决?是否有更好的方法来增加分配给huffcoder
的内存?
答案 0 :(得分:3)
我看到的错误是realloc
已经是malloc
和free
的组合。 free
此处的调用是不必要且错误的:
struct huffchar * updatedTree = realloc(ourHuffCoder -> tree, (ourHuffCoder->sizeOfTree+1)*sizeof(struct huffchar));
free(ourHuffCoder -> tree);
ourHuffCoder -> tree = updatedTree;
也就是说,当我们调用realloc(ptr)
时,ptr
被释放,并返回一个新的指针。分配器有时可以通过调整旧对象的大小来优化流程。
不需要释放ptr
,实际上我们绝对不能这样做。
如果我们不在乎优化,我们几乎可以这样写realloc
:
#include <string.h>
#include <stdlib.h>
#define min(a, b) ((a) < (b) : (a) : (b))
void *our_realloc(void *oldptr, size_t newsize)
{
if (newsize == 0) {
free(oldptr);
return 0;
} else {
void *newptr = malloc(newsize);
if (oldptr) {
size_t oldsize = __obtain_old_size_in_nonportable_way(oldptr);
memcpy(newptr, oldptr, min(oldsize, newsize));
free(oldptr); // !!!!
}
return newptr;
}
}
即使在realloc
返回“相同”指针的情况下,程序也无法轻易分辨出来。旧指针已失效,因此任何使用都是未定义的行为:
newptr = realloc(oldptr, size);
if (newptr == oldptr) { // did it really move?
此处使用oldptr
在技术上是未定义的行为。我们永远不会同时持有两个指针。我们已经用另一笔交易了,交易发生在realloc
黑盒内。
我们可以捕获打印的图像:
char oldptr_txt[64], newptr_txt[64];
snprintf(oldptr_txt, sizeof oldptr_txt, "%p", (void *) oldptr);
newptr = realloc(oldptr, size);
snprintf(newptr_txt, sizeof newptr_txt, "%p", (void *) newptr);
if (strcmp(oldptr_txt, newptr_txt) == 0) {
// almost certainly stayed in place
} else {
// almost certainly moved
}