删除无法识别List中的指针分配

时间:2016-04-18 05:53:07

标签: c++ pointers delete-operator

当我尝试在指向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;
}

with main:

#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;
}

2 个答案:

答案 0 :(得分:3)

你这么做的那一刻,你就陷入了灾难:

void Graph::newDirectedEdge(int v1, int v2) {
    Vertex * vertex2 = adjList[v2].front();
    adjList[v1].push_back(vertex2);
}

问题在于您没有区分拥有指针的人。在这种情况下,您只需将指针复制到列表中即可。但是当你到~Graph时,你会删除列表中的所有指针。其中一些是new获得的,有些是由上述函数复制的。

所以错误是正确的:没有分配指针。发生了什么事情,你已经删除它,然后你删除了它的副本。

您需要重新考虑您的设计并考虑指针所有权。或者您可以使用大锤方法将所有内容转换为std::shared_ptr。但我实际上并不推荐这样做。

图表的常用方法是存储所有顶点(在std::vector中),然后像您一样以单独的结构连接。然后在析构函数中,你只需翻阅向量。您甚至可以将此作为一个学习如何使用std::unique_ptr的机会。 =)

答案 1 :(得分:0)

newDirectedEdge功能出现问题吗? 在它的实现中,它再次复制指针和插入列表,然后列表中的一个地址的两个指针,第一次删除是正常的,第二次...崩溃......