在结构中的指针上使用 free() 释放整个结构的内存
Using free() on a pointer within a struct frees memory for the entire struct
我的程序中有两个 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
时,我 malloc ourHuffCoder
a huffcoder
的大小,然后将 X 许多元素的内存 malloc 到 struct huffchar * tree
:
struct huffcoder * ourHuffChar = malloc(sizeof(struct huffcoder));
ourHuffChar -> tree = malloc(sizeof(struct huffchar)*NUM_CHARS);
不过,我以后需要把这棵树变大,不知道最后这棵树上会有多少元素。换句话说,每次我添加一个元素时,我都会创建一个 realloc()
大一个元素的新树,然后将 huffcoder
中 tree
的指针设置为这个新的 updatedTree
.
以下代码行旨在实现此目的:
struct huffchar * updatedTree = realloc(ourHuffCoder -> tree, (ourHuffCoder->sizeOfTree+1)*sizeof(struct huffchar));
free(ourHuffCoder -> tree);
ourHuffCoder -> tree = updatedTree;
请注意,在将 tree
指针更新为 updatedTree
之前,我使用行 free(ourHuffCoder -> tree)
释放之前分配给树的内存。但是,当我到达 free(ourHuffCoder -> tree)
行时,分配给 HuffCoder 指针 ourHuffCoder
的 entirety 的内存被释放,而不仅仅是分配给 [=23] 的内存=].
这是我的变量 window before 运行ning 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;
这显然不是我应该做的,因为我很快就会 运行 内存不足,但我想看看 huffcoder
中指向 tree
的指针是否会更新指向 updatedTree
,它有:
之前 ourHuffCoder -> tree = updatedTree;
ourHuffCoder -> tree = updatedTree;
之后
我的问题是,为什么分配给整个 huffcoder
结构的内存被释放,而不是只分配给 tree
的内存?我该如何解决这个问题?有没有更好的方法来增加分配给 tree
的内存?
我看到的错误是 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
returns "same" 指针的情况下,程序也无法轻易辨别。旧指针已经失效,所以对它的任何使用都是未定义的行为:
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
}
我的程序中有两个 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
时,我 malloc ourHuffCoder
a huffcoder
的大小,然后将 X 许多元素的内存 malloc 到 struct huffchar * tree
:
struct huffcoder * ourHuffChar = malloc(sizeof(struct huffcoder));
ourHuffChar -> tree = malloc(sizeof(struct huffchar)*NUM_CHARS);
不过,我以后需要把这棵树变大,不知道最后这棵树上会有多少元素。换句话说,每次我添加一个元素时,我都会创建一个 realloc()
大一个元素的新树,然后将 huffcoder
中 tree
的指针设置为这个新的 updatedTree
.
以下代码行旨在实现此目的:
struct huffchar * updatedTree = realloc(ourHuffCoder -> tree, (ourHuffCoder->sizeOfTree+1)*sizeof(struct huffchar));
free(ourHuffCoder -> tree);
ourHuffCoder -> tree = updatedTree;
请注意,在将 tree
指针更新为 updatedTree
之前,我使用行 free(ourHuffCoder -> tree)
释放之前分配给树的内存。但是,当我到达 free(ourHuffCoder -> tree)
行时,分配给 HuffCoder 指针 ourHuffCoder
的 entirety 的内存被释放,而不仅仅是分配给 [=23] 的内存=].
这是我的变量 window before 运行ning 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;
这显然不是我应该做的,因为我很快就会 运行 内存不足,但我想看看 huffcoder
中指向 tree
的指针是否会更新指向 updatedTree
,它有:
之前 ourHuffCoder -> tree = updatedTree;
ourHuffCoder -> tree = updatedTree;
之后
我的问题是,为什么分配给整个 huffcoder
结构的内存被释放,而不是只分配给 tree
的内存?我该如何解决这个问题?有没有更好的方法来增加分配给 tree
的内存?
我看到的错误是 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
returns "same" 指针的情况下,程序也无法轻易辨别。旧指针已经失效,所以对它的任何使用都是未定义的行为:
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
}