提问人:Jason 提问时间:10/27/2023 更新时间:10/27/2023 访问量:81
即使我在 C 中自由,也肯定丢失了记忆
Definitely lost memory even though I free in C
问:
我想创建一个函数,当给定一个结构体时,该结构体中有一个指向相同类型的另一个结构的指针,它会找到所有指针并释放它们。
结构为:
typedef struct example_ {
uint16_t something;
bool blabla;
struct example_ *further_in;
} example;
我创建的用于释放每个指针的函数是:
bool free_examples(example p) {
bool isCounting = true;
int16_t count = 0;
example firstexample = p;
while (isCounting) // counts how many examples there are
{
if (p.further_in == NULL)
{
isCounting = false;
}
else if (p.further_in != NULL)
{
count++;
p = *(p.further_in);
}
}
p = firstexample;
example *n = malloc(sizeof(example));
for (int i = 0; i < count; i++) // frees every pointer?
{
n = p.further_in;
free(p.further_in);
p = *(n);
}
free(n);
return true;
}
首先,我是编程和 C 的新手,所以我甚至不知道我的代码是否做了我想做的事情。
其次,我的问题是,当我通过 valgrind 运行它时,它返回的这一行肯定丢失了 16 个字节:
example *n = malloc(sizeof(example));
正如你所看到的,我释放了“n”,稍后。我不明白它怎么仍然泄露。
提前感谢您的任何帮助!
答:
3赞
Vlad from Moscow
10/27/2023
#1
此代码片段:
p = firstexample;
example *n = malloc(sizeof(example));
for (int i = 0; i < count; i++) // frees every pointer?
{
n = p.further_in;
free(p.further_in);
p = *(n);
}
free(n);
至少会产生内存泄漏,并且具有未定义的行为。
在这一行中:
example *n = malloc(sizeof(example));
有分配的内存,其地址分配给指针。然后在下面的 for 循环中,指针被重新分配:n
n
n = p.further_in;
因此,分配的内存的地址将丢失。
还有这个声明
p = *(n);
访问已释放的内存,从而导致未定义的行为。
此外,也不清楚该类型的传递对象是否为:example
bool free_examples(example p) {
^^^
是否存储在动态分配的内存中。如果它确实被放置在动态分配的内存中,那么它也应该被释放,并且至少应该声明该函数,如下所示:
void free_examples(example *p) {
^^^
返回类型 bool 也没有意义。
请注意,相对于释放已分配内存的过程,计算非空指针的数量没有意义,并且效率低下且冗余。
如果你有一个单向链表,其中列表的所有节点都是动态分配的,那么该函数可以按以下方式显示:
void free_examples( example **p )
{
while ( *p != NULL )
{
example *current = *p;
*p = ( *p )->further_in;
free( current );
}
}
如果在调用方中,您有一个指向列表的第一个节点的指针,该节点是动态分配的,例如:
example *head = malloc( sizeof( example ) );
然后函数被调用如下:
free_examples( &head );
评论
0赞
Jason
10/27/2023
感谢您的详细回答!我现在更了解它了。
1赞
Vlad from Moscow
10/27/2023
@TedLyngmo谢谢。这是一个错别字。我已经更新了代码。
0赞
Vlad from Moscow
10/27/2023
@Jason完全没有。不客气:)
2赞
Ted Lyngmo
10/27/2023
#2
您当前正在访问内存之前释放内存。一个简单的解决方案是创建一个指针,如下所示:next
void free_examples(example **p) {
if (p == NULL) return;
for (example *curr = *p, *next; curr; curr = next) {
next = curr->further_in; // get the pointer to the next `example` before ...
free(curr); // ... freeing what `curr` points at
}
*p = NULL;
}
然后,您需要通过获取指针的地址来调用它:example
free_examples(&n);
评论
n = p.further_in;
这将丢弃您从 收到的值。你将永远无法释放你分配的东西。malloc
p = *(n);
这将取消引用您之前刚刚释放的一行。复制指针不允许在释放内存后访问内存。p.further_in