【发布时间】:2016-04-18 05:53:06
【问题描述】:
当我尝试对指向 struct Vertex 的指针调用 delete(使用 Vertex * v = new Vertex 分配,然后在我的类析构函数中成功使用并存储在 std::list 中时,我收到此运行时错误:
graphtake3(12325,0x100082000) malloc: *** error for object 0x100200340: pointer being freed was not allocated
***
指针肯定是被分配的,因为应用程序运行良好,并且一切都在堆栈跟踪中显示,但由于某种原因,delete 似乎无法释放它们。这里发生了什么,为什么不删除工作?
以下是相关的缩写代码:
#include <vector>
#include <list>
#include <iostream>
#include <string>
enum Color {BLACK, GREY, WHITE};
struct Vertex {
int id;
std::string name;
Color color;
Vertex();
Vertex(std::string name);
~Vertex();
};
class Graph {
std::vector<std::list<Vertex *>> adjList;
public:
Graph();
Graph (int nodeCount);
~Graph();
int newVertex();
int newVertex(std::string name);
void newUnDirectedEdge(int v1, int v2);
void newDirectedEdge(int v1, int v2);
std::list<Vertex*> getConnections(int v);
friend std::ostream& operator<<(std::ostream& os, const Graph& g);
};
和
#include "Graph.hpp"
Vertex::Vertex() {
color = WHITE;
}
Vertex::Vertex(std::string name) {
this->name = name;
color = WHITE;
}
Vertex::~Vertex() {
}
Graph::Graph() {
}
Graph::Graph(int nodeCount) {
adjList.reserve(nodeCount);
}
Graph::~Graph(){
for (int i = 0; i<adjList.size(); i++) {
for (std::list<Vertex*>::iterator iterator = adjList[i].begin(), end = adjList[i].end(); iterator !=end; iterator++) {
delete (*iterator); //fails
}
}
}
int Graph::newVertex() {
Vertex * v = new Vertex();
adjList.push_back(std::list<Vertex *>(1, v));
v->id= (int)adjList.size()-1;
return v->id;
}
int Graph::newVertex(std::string name) {
Vertex * v = new Vertex();
adjList.push_back(std::list<Vertex *>(1, v));
v->id= (int)adjList.size()-1;
v->name= name;
return v->id;
}
void Graph::newUnDirectedEdge(int v1, int v2) {
newDirectedEdge(v1, v2);
newDirectedEdge(v2, v1);
}
void Graph::newDirectedEdge(int v1, int v2) {
Vertex * vertex2 = adjList[v2].front();
adjList[v1].push_back(vertex2);
}
std::list<Vertex*> Graph::getConnections(int v) {
return adjList[v];
}
std::ostream& operator<<(std::ostream& os, const Graph& g) {
for (int i = 0; i<g.adjList.size(); i++) {
for (std::list<Vertex*>::const_iterator iterator = g.adjList[i].begin(), end = g.adjList[i].end(); iterator !=end; iterator++) {
os << (*iterator)->id << " (" << (*iterator)->name << ") ";
}
os << '\n';
}
return os;
}
与主:
#include <iostream>
#include "Graph.hpp"
int main(int argc, const char * argv[]) {
Graph graph(5);
int v1 = graph.newVertex("Paris");
int v2 = graph.newVertex("London");
int v3 = graph.newVertex("Lyon");
int v4 = graph.newVertex("Nice");
int v5 = graph.newVertex("Marseille");
int v6 = graph.newVertex("La Rochelle");
int v7 = graph.newVertex("Toulon");
graph.newUnDirectedEdge(v2, v1);
graph.newUnDirectedEdge(v1, v3);
graph.newUnDirectedEdge(v1, v4);
graph.newUnDirectedEdge(v3, v4);
graph.newUnDirectedEdge(v5, v4);
graph.newUnDirectedEdge(v7, v5);
std::cout << graph;
return 0;
}
【问题讨论】:
-
请发布一个最小但完整的演示,读者可以尝试。这听起来像是一个三规则问题。但没有代码就无法确定。
-
@Cheersandhth.-Alf 好的,我添加了一个更完整的实现
-
感谢您的更新,顺便说一句。将
Graph(const Graph&) = delete;(假设您使用 C++11)添加到您的Graph类声明中。如果您的代码编译开始在各个地方呕吐,那么您肯定违反了rule-of-three。 -
@WhozCraig 好的,我添加了我的
main()。我还没有实现复制构造函数,所以我是,但是在这种情况下如何阻止删除工作? -
@TheInnerParty 我刚刚运行了你的代码,在这种情况下它不会因为
Graph从未被复制(想想如果它会发生什么,两个Graph对象有两个@987654335 @ 都包含 same 指针)。顺便说一句,这与您的实际问题密切相关。您的邻接列表可以共享>指向相同顶点对象的指针。至少从我所看到的来看,他们似乎是这样做的。清除列表后,每个 other 列表都包含指向刚刚清除的列表中的一个或多个顶点的指针现在悬空,并且使用它们会调用未定义的行为。
标签: c++ pointers delete-operator