C ++从向量中删除指针会导致堆错误
Posted
技术标签:
【中文标题】C ++从向量中删除指针会导致堆错误【英文标题】:C++ deleting pointers from vector causes heap error 【发布时间】:2014-11-13 11:20:36 【问题描述】:我有一个指向基类对象的指针向量,然后我将派生类的对象存储在其中。我添加指针的方式很明显
std::vector<Element*> mvGates;
...
mvGates.push_back(new Node(x, y));
当我的程序即将关闭时,这些指针在'for'循环中被释放
for (int i=0; i<mvGates.size(); ++i)
delete mvGates[i];
在这一行,我的调试器(我正在使用 Qt Creator)显示如下几行:
Heap block at 14E50F50 modified at 14E50F84 past requested size of 2c
Invalid address specified to RtlFreeHeap( 00030000, 14E50F58 )
可能是什么原因,我做错了什么?我知道我没有向您展示完整的代码,因为它很长,但也许足以告诉我我的错误。可能你会推荐我使用智能指针。我想我会这样做,但这并不能回答我的问题——这段代码有什么问题。
编辑:
这是一个非常简单的错误,你不可能在这里注意到它。在 Node 类中,我声明了 some_type array[0];
我一直将它用作 2 元素数组。我不知道为什么它没有导致 SIGSEGV 但它是导致堆错误的原因。
【问题讨论】:
也许你已经释放了内存?也许您更改了一个或多个指针?也许您认为一个对象属于一个子类,但它实际上属于另一个,并且您写入不属于该类的内存(并覆盖其他一些对象内存)?而你确实让你的析构函数virtual
?无论如何,问题不在于您在问题中显示的代码,而在于其他地方。
你的 Element 类是否实现了虚拟析构函数?
您的Element
的析构函数是否标记为virtual
?查看错误消息,它似乎确实删除了小于实际对象大小(缺少 2c 个字节),这表明 Element*
已删除,但未调用 Node*
析构函数。这意味着,您的基类中没有虚拟析构函数。
向量mvGates
可能已损坏,或者析构函数中存在错误,或者您可能已经删除了节点,或者某些不相关的内存部分可能已损坏,或者其他原因可能已经发生了。这是不可能的。
您没有指定您的标准,但如果您可以使用 c++11,请考虑切换到智能指针en.cppreference.com/w/cpp/memory/shared_ptr 让对象为您记账,只需正确定义类即可。
【参考方案1】:
您的 std::vector 包含指向 Element 类实例的指针,但您正在使用 Node 类实例填充它。 由于编译器没有抱怨,我们可以放心地假设 Node 扩展了 Element。
问题在于,当您删除这些元素时,您将它们称为元素。除非您正确覆盖 Element 析构函数,否则删除操作将调用 Element::~Element() 而不是 Node::~Node()
在你的类定义中确保析构函数是虚拟的:
class Element
virtual ~Element()
//Element cleanup
//....
;
【讨论】:
这似乎是一个很可能的错误,但在我的情况下不是这样。首先,Element 和 Node 都没有分配内存,所以我不需要定义它们的析构函数。无论如何,我有那些空的析构函数,而 Element 析构函数是虚拟的。【参考方案2】:在您的代码中,您正在使用索引访问向量中的每个对象,并且您正在删除它们。但是,除了“Pierluigi”所说的(虚拟~问题),你不应该使用迭代器而不是直接使用索引来访问每个对象并删除它们吗?
【讨论】:
【参考方案3】:你在增量部分弄错了。它的 i++ 你不需要 ++i。
如果您使用 ++i,它将在循环到 for 循环之前递增,因此在迭代器编号处它指的是实际上不存在的 mvGates[i]。只有向量的范围是从 0 到 length-1。
for (int i=0; i<mvGates.size(); i++)
delete mvGates[i];
【讨论】:
在这种情况下没关系,当在 for 循环的增量表达式中指定时,两个版本都可以。它们在下一次迭代之前完全执行,并且值仍然增加。如果将其放入operator[]
的参数中,将是一个问题。另外,您的陈述是错误的,在循环开始之前它没有增加。 ++i
递增并返回新值,而i++
也递增但返回递增前的前一个值。以上是关于C ++从向量中删除指针会导致堆错误的主要内容,如果未能解决你的问题,请参考以下文章
在 ForEach 循环中删除项目会导致致命错误:索引超出范围
删除 Java ArrayList 中的重复对象会导致并发修改错误 [重复]