我无法理解C ++中的一些基本内存管理原则。此代码是循环的一部分,循环是将迷宫文件读入2D矢量的函数的一部分。
根据Valgrind的说法,以下代码导致内存泄漏......
请注意t
是一个MazeNode
对象,而verts
是t
类中的一个向量,它包含指向节点对象的指针(不要与{{1对象):
MazeNode
最初我没有在删除它们之前将每个指针设置为NULL,但是会出现分配错误。所以我只是将它们设置为NULL并且我的代码可以工作。我想我真的很困惑为什么这会导致内存泄漏以及为什么我需要将指针设置为NULL。可能有一种更容易的非指针方式来做到这一点,但也许这个问题将帮助我更好地理解内存管理。
谢谢大家。
编辑:这是MazeNode类(这就是't')(也可以原谅我写这个类的懒惰,让每个人都像结构一样公开)
node* top = new node(TOP, rowCount, i, t.type);
node* bot = new node(BOTTOM, rowCount, i, t.type);
node* left = new node(LEFT, rowCount, i, t.type);
node* right = new node(RIGHT, rowCount, i, t.type);
t.verts.push_back(top);
t.verts.push_back(bot);
t.verts.push_back(left);
t.verts.push_back(right);
temp.push_back(t);
top = NULL;
bot = NULL;
left = NULL;
right = NULL;
delete top;
delete bot;
delete left;
delete right;
节点类:
class MazeNode
{
public:
void setType(char c);
char getChar();
NodeType type;
vector<Direction> visitedFrom;
vector<node*> verts;
};
EDIT2:谢谢大家。我现在明白了这个问题。我改变了指针对象的向量,这样我就不再使用指针了。
答案 0 :(得分:9)
在添加空赋值之前,您的代码存在一个与内存泄漏不同(更糟糕)的问题:存储并且可能还使用了一个迷路指针,即一个指向解除分配内存的指针。
通过添加空赋值使其成为内存泄漏会使其更好,但不会太多。
真正的解决方案是在你对它们调用delete之后不要在任何地方保留任何指针。
也就是说,这里不要push_back
或不delete
。
答案 1 :(得分:4)
您将指针放入容器中,然后删除指针。当您的代码稍后尝试使用这些指针时,它们无效并导致崩溃。
通过在删除它们之前将指针设置为NULL,您最终根本不删除它们 - 删除NULL指针不会执行任何操作。但是现在没有什么可以在以后删除这些对象,并且会出现内存泄漏。
您需要在代码中找到一些您不再使用指针的位置,并将其删除。
编辑:当然我应该提到像std::shared_ptr
之类的智能指针完全消除了这个麻烦,因为它会自动删除对象。
答案 2 :(得分:2)
在删除它们之前,您将值设置为NULL,因此您尝试删除NULL并且不删除任何内容。尝试将删除调用移到NULL调用之上。
答案 3 :(得分:2)
这种混乱正是我为这类事物创建宏的原因:
#define delobj(obj) (delete obj, obj = NULL)
你会像这样使用它:
delobj(top);
delobj(bot);
delobj(left);
delobj(right);
答案 4 :(得分:2)
错误是使用指针向量。据你说,顶点是:
vector<node*> verts;
但它应该是这样的:
vector<node> verts;
在第一种情况下,当你push_back()指针时,没关系,但是当你pop_back或以其他方式重新调整向量大小时,指针是向量的“内容”,并且被解除分配,但不是指针指向的是什么,即节点。因此节点泄漏。但在第二种情况下,节点是向量的“部分”,并且作为重新调整向量大小的一部分被分配/解除分配。
这里的模式可能表示Java / C#背景,因为容器中的“new-ing”在这些语言中非常常见,但要在C ++中这样做,你需要一个智能指针容器(如{{1这可能超出了问题的范围。但是在这些语言中,对引用类型的每个引用都是“智能指针”(或多或少),因此这是自动完成的。 C ++不是那样的。
您需要更改代码以使用vector<shared_ptr<node>>
(并更改您重新启动它的方式),或者您需要在向量缩小时显式取消分配节点。
答案 5 :(得分:0)
更改为:
delete top;
delete bot;
delete left;
delete right;
top = NULL;
bot = NULL;
left = NULL;
right = NULL;
它应该有用。