【发布时间】:2020-04-15 02:34:38
【问题描述】:
我正在尝试用 C 语言实现 Barnes-Hutt 树,但在释放树时遇到了问题。
树中的节点如下:
struct node {
int is_external;
quad q;
body *b;
node *nw;
node *ne;
node *sw;
node *se;
};
我用来释放它们的功能是
void free_node(node *n) {
// free subnodes
if (n->nw != NULL) {
free_node(n->nw);
}
if (n->ne != NULL) {
free_node(n->ne);
}
if (n->sw != NULL) {
free_node(n->sw);
}
if (n->se != NULL) {
free_node(n->se);
}
// free this node's body
if (!n->is_external) {
free(n->b);
}
free(n);
}
(我没有释放外部节点的主体,因为它们被保留用于模拟的下一次迭代)。
但是,当我检查内存泄漏时,我得到了
72 bytes in 1 blocks are definitely lost in loss record 24 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100002413: insert_in_node (bh_tree.c:165)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 25 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100001E64: insert_in_node (bh_tree.c:108)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 26 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x10000251D: insert_in_node (bh_tree.c:173)
by 0x100001F97: insert_in_node (bh_tree.c:118)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 27 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100002627: insert_in_node (bh_tree.c:181)
by 0x10000209B: insert_in_node (bh_tree.c:126)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x100001F97: insert_in_node (bh_tree.c:118)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 28 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x10000206C: insert_in_node (bh_tree.c:124)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x10000209B: insert_in_node (bh_tree.c:126)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x100001F97: insert_in_node (bh_tree.c:118)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 29 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100002170: insert_in_node (bh_tree.c:132)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 30 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100002627: insert_in_node (bh_tree.c:181)
by 0x100001E93: insert_in_node (bh_tree.c:110)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 31 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100002627: insert_in_node (bh_tree.c:181)
by 0x10000219F: insert_in_node (bh_tree.c:134)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x100001E93: insert_in_node (bh_tree.c:110)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 32 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x100002309: insert_in_node (bh_tree.c:157)
by 0x10000219F: insert_in_node (bh_tree.c:134)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x10000219F: insert_in_node (bh_tree.c:134)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x100001E93: insert_in_node (bh_tree.c:110)
by 0x100001693: main (sim.c:115)
72 bytes in 1 blocks are definitely lost in loss record 33 of 51
at 0x100111CF5: malloc (in /usr/local/Cellar/valgrind/HEAD-9f4f524/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
by 0x100001B95: subnode (bh_tree.c:70)
by 0x10000206C: insert_in_node (bh_tree.c:124)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x10000219F: insert_in_node (bh_tree.c:134)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x10000219F: insert_in_node (bh_tree.c:134)
by 0x100002675: insert_in_node (bh_tree.c:188)
by 0x100001E93: insert_in_node (bh_tree.c:110)
by 0x100001693: main (sim.c:115)
都指向下面malloc
node n_sub;
n_sub.is_external = 1;
n_sub.q = subquad(n.q, k);
n_sub.nw = NULL;
n_sub.ne = NULL;
n_sub.sw = NULL;
n_sub.se = NULL;
n_sub.b = malloc(sizeof(body));
*n_sub.b = (body) {.id=EMPTY};
return n_sub;
}
但我相当肯定我正确地释放了所有这些。有什么想法可能会出错吗?
【问题讨论】:
-
我们需要看到minimal verifiable example。根据定义,您不知道问题出在哪里。因此,通过有选择地显示代码,您可能已经消除了实际的根本原因。因此,请构建一个我们可以自己运行以查看问题的最小示例。 “我没有释放外部节点的主体”:例如,我们如何确保正确完成并且最终释放了这些主体。我们不能,没有所有相关代码。
-
struct
body是如何定义的?它的尺寸是 72 吗?你有没有将is_external设置为 0? -
在释放指针指向的内存后将指针清空是一种很好的做法;这将有助于发现很多错误。
-
注意:如果
n->nw->se == n迟早会中断。最好将其拆分为一个处理算法的层(可能使用nw等链接)和一个进行内存分配的层(可能将所有节点保存在一个数组中)。 -
@SteveFriedl 感谢您的提示。我会确保在未来这样做。
标签: c memory-management struct memory-leaks malloc