释放C中的树结构
Freeing a tree structure in C
我在我的 C 程序中使用结构树,其中的结构设置如下:
typedef struct SymbolTable_t
{
int id;
Symbol symbols[size];
int count;
struct SymbolTable_t * parent;
int scopeCount;
struct SymbolTable_t * childScopes[size];
int isM;
} SymbolTable;
当我创建一个新的 SymbolTable 时,我会像这样为子作用域分配内存:
SymbolTable *t = malloc(sizeof(*t));
// other stuff ...
for(int i = 0; i < size; i++)
{
childScopes[i] = malloc(sizeof(SymbolTable)); // <---- line 41
}
在程序结束时,当我想释放分配给它们的内存时,我编写了一个递归函数:
void freeSymbolTables(SymbolTable* root)
{
if(root == NULL) return;
for(int i = 0; i < size; i++)
{
freeSymbolTables(root->childScopes[i]);
}
free(root);
}
请注意,我并没有真正使用整个 childScopes,因此只有其中一些会在程序结束时实际指向某些内容。我认为这很好但是 运行ning 在 valgrind 中它告诉我大量内存是 'definitely lost' 在第 41 行,我认为这意味着指针超出范围而没有调用 free程序生命周期结束。我不确定这里出了什么问题,因为我认为这应该释放所有内存。
最小可重现示例
#include <stdio.h>
#include <stdlib.h>
#define s_size 40
typedef struct SymbolTable_t
{
struct SymbolTable_t * s[s_size];
int count;
} SymbolTable;
SymbolTable* createSymbolTable()
{
SymbolTable* t = malloc(sizeof *t);
t->count = 0;
for(int i = 0; i < s_size; i++)
{
t->s[i] = malloc(sizeof t->s[i]);
}
return t;
}
void freeSymbolTable(SymbolTable* root)
{
if(root == NULL) return;
for(int i = 0; i < root->count; i++) freeSymbolTable(root->s[i]);
for(int i = root->count; i < s_size; i++) free(root->s[i]);
free(root);
}
void addChildScope(SymbolTable* parent, SymbolTable* child)
{
parent->s[parent->count++] = child;
}
int main()
{
SymbolTable *t = createSymbolTable();
SymbolTable *c = createSymbolTable();
addChildScope(t, c);
freeSymbolTable(t);
return 0;
}
当我 运行 这样做时,valgrind 告诉我肯定丢失了 8 个字节,甚至认为我认为我的函数应该释放所有内存。
你基本上是在做:
// in createSymbolTable()
t->s[0] = malloc(...);
然后:
// in addChildScope()
parent->s[0] = child; // malloc(...) from above is just lost...
您可以使用以下方法“修补”/解决它:
void addChildScope(SymbolTable* parent, SymbolTable* child) {
free(parent->s[parent->count]);
parent->s[parent->count++] = child;
}
但总的来说,如果内存从未被使用过,我认为在 createSymbolTable
中分配任何内容毫无意义。无论如何不要在 createSymbolTable
中分配它,内存不会被使用。
此外,理论上(但从未使用过,所以无所谓):
t->s[i] = malloc(sizeof t->s[i]);
可疑 - 应该是:
t->s[i] = malloc(sizeof *t->s[i]);
我在我的 C 程序中使用结构树,其中的结构设置如下:
typedef struct SymbolTable_t
{
int id;
Symbol symbols[size];
int count;
struct SymbolTable_t * parent;
int scopeCount;
struct SymbolTable_t * childScopes[size];
int isM;
} SymbolTable;
当我创建一个新的 SymbolTable 时,我会像这样为子作用域分配内存:
SymbolTable *t = malloc(sizeof(*t));
// other stuff ...
for(int i = 0; i < size; i++)
{
childScopes[i] = malloc(sizeof(SymbolTable)); // <---- line 41
}
在程序结束时,当我想释放分配给它们的内存时,我编写了一个递归函数:
void freeSymbolTables(SymbolTable* root)
{
if(root == NULL) return;
for(int i = 0; i < size; i++)
{
freeSymbolTables(root->childScopes[i]);
}
free(root);
}
请注意,我并没有真正使用整个 childScopes,因此只有其中一些会在程序结束时实际指向某些内容。我认为这很好但是 运行ning 在 valgrind 中它告诉我大量内存是 'definitely lost' 在第 41 行,我认为这意味着指针超出范围而没有调用 free程序生命周期结束。我不确定这里出了什么问题,因为我认为这应该释放所有内存。
最小可重现示例
#include <stdio.h>
#include <stdlib.h>
#define s_size 40
typedef struct SymbolTable_t
{
struct SymbolTable_t * s[s_size];
int count;
} SymbolTable;
SymbolTable* createSymbolTable()
{
SymbolTable* t = malloc(sizeof *t);
t->count = 0;
for(int i = 0; i < s_size; i++)
{
t->s[i] = malloc(sizeof t->s[i]);
}
return t;
}
void freeSymbolTable(SymbolTable* root)
{
if(root == NULL) return;
for(int i = 0; i < root->count; i++) freeSymbolTable(root->s[i]);
for(int i = root->count; i < s_size; i++) free(root->s[i]);
free(root);
}
void addChildScope(SymbolTable* parent, SymbolTable* child)
{
parent->s[parent->count++] = child;
}
int main()
{
SymbolTable *t = createSymbolTable();
SymbolTable *c = createSymbolTable();
addChildScope(t, c);
freeSymbolTable(t);
return 0;
}
当我 运行 这样做时,valgrind 告诉我肯定丢失了 8 个字节,甚至认为我认为我的函数应该释放所有内存。
你基本上是在做:
// in createSymbolTable()
t->s[0] = malloc(...);
然后:
// in addChildScope()
parent->s[0] = child; // malloc(...) from above is just lost...
您可以使用以下方法“修补”/解决它:
void addChildScope(SymbolTable* parent, SymbolTable* child) {
free(parent->s[parent->count]);
parent->s[parent->count++] = child;
}
但总的来说,如果内存从未被使用过,我认为在 createSymbolTable
中分配任何内容毫无意义。无论如何不要在 createSymbolTable
中分配它,内存不会被使用。
此外,理论上(但从未使用过,所以无所谓):
t->s[i] = malloc(sizeof t->s[i]);
可疑 - 应该是:
t->s[i] = malloc(sizeof *t->s[i]);