我从以下代码中获取内存泄漏:
struct Node {
Node *children[20];
int value;
Node();
~Node();
};
Node::Node() {
for(int i=0; i<20; i++) {
children[i] = NULL;
}
}
void Node::insert(int x) {
Node *n = this;
for(int i=0; i<20; i++) {
if(n->children[i] == NULL) {
n->children[i] = new Node();
n->children[i]->value = x;
}
n = n->children[i];
}
}
用Valgrind检查,显然我从这一行得到了泄漏:
n->children[i] = new Node();
这是使用构造函数的错误方法吗?
或者Valgrind检查误导?
Valgrind错误讯息:
505 (448 direct, 57 indirect) bytes in 2 blocks are definitely lost in loss record 2 of 3
at 0x4C2B1C7: operator new(unsigned long)
by 0x401A4F: Node::insert
by 0x4015FA: main
LEAK SUMMARY:
definitely lost: 448 bytes in 2 blocks
indirectly lost: 57 bytes in 2 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 72,704 bytes in 1 blocks
suppressed: 0 bytes in 0 blocks
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
我有的析构函数:
Node::~Node() {
for(int i=0; i<20; i++) {
delete children[i];
children[i] = NULL;
}
}
主要:
int main() {
Node *n = new Node();
.
.
.
delete n;
n = NULL;
return 0;
}
答案 0 :(得分:1)
您不是要删除孩子。正如Axel所回答的,你应该在你的析构函数中添加一个删除。或者更好的是,使用unique_ptr数组,当它们超出范围时,它将负责销毁节点。
答案 1 :(得分:0)
你永远不会删除子指针。
您应该在Node类析构函数中删除子数组的每个已分配指针。
就像那样:
Node::~Node()
{
for (int i = 0; i < 20; ++i)
{
delete children[i];
}
}
此外,如果有任何其他方法替换子数组中的指针,则必须在替换之前删除前一个指针,如下所示:
...
delete n->children[i];
n->children[i] = new Node();
...
或
...
delete n->children[i];
n->children[i] = p; // where p is a pointer of Node
...
有关信息,您必须调用 delete 来销毁和释放您在堆上构造的每个对象(使用 new )。
您还可以使用smartpointer来避免管理儿童成员的破坏。
答案 2 :(得分:0)
我看到一个新的,但没有删除,也没有智能指针。这意味着您可以在不释放内存的情况下分配内存。 (至少你没有告诉我们Node
的析构函数应该在哪里完成。)
除此之外,您的代码中存在一些缺陷:
使用智能指针分配内存:
struct Node {
unique_ptr<Node> children[20]; //consider switching to std::array
int value;
// no destructor needed, because unique_ptr takes care of itself
Node (int newValue);
void insert(int valueToInsert);
};
void Node::insert(int valueToInsert) {
auto freeSpot = //find the point where you want to insert the new node
if ( /*freeSpot is a valid location*/ )
*freeSpot = make_unique<Node>(x);
}
Node::Node(int newValue)
: value(newValue)
{}
这将是你可以做的第一次重构