简体   繁体   English

性能崩溃 C++(标准向量 bad_allocation)

[英]Performance collapse C++ (std vector bad_allocation)

Following code is about searching for neighbours in realtime.以下代码是关于实时搜索邻居的。 As soon as a new node is added to my graph, the function updateSeqNeighbours for this node is called.一旦一个新节点被添加到我的图中,这个节点的函数updateSeqNeighbours就会被调用。 What I know is, that the new node is definitely neighbour to the last one added.我所知道的是,新节点绝对是添加的最后一个节点的邻居。 In the next step I use this fact to look in the neighbourhood of the previously added node, find the one closest to the new and then search this neighbourhood for the closest neighbour.在下一步中,我使用这个事实来查看先前添加的节点的邻域,找到最接近新节点的一个,然后在这个邻域中搜索最近的邻域。

I repeat this only for example 3 times, to limit the number of neighbours for one node to 4 to keep a constant time frame for calculation.我仅重复此示例 3 次,以将一个节点的邻居数量限制为 4,以保持计算的恒定时间范围。 It works wonderful, except for after ~30 nodes the calculation time increases very fast with every additional node resulting in a bad_alloc exception.它工作得很好,除了在 ~30 个节点之后计算时间增加得非常快,每个额外的节点导致bad_alloc异常。

#ifndef GRAPH_NODE_H_
#define GRAPH_NODE_H_

#include <vector>
#include <cmath>

#include <iostream>

using namespace std;

class Node {
public:
    double x;
    double y;

    Node* nodePrev;

    vector<Node> seqNeighbours;

    //Constructor
    Node();
    Node(double x, double y);
    virtual ~Node();

    //Operator functions
    Node& operator=(const Node& n);

    //Get&Set
    int getID();

    //Public member functions
    void addNeighbour(Node& n);

    bool isSeqNeighbour(int ID);

    int updateSeqNeighbours();

    double distanceTo(Node& n);

private:
    static int count;
    int ID;

    void _setDefaults();
};

int Node::count = 0;

Node::Node() {
    _setDefaults();
}

Node::Node(double x, double y) {
    _setDefaults();
    this->x = x;
    this->y = y;
}

Node::~Node() {
    // TODO Auto-generated destructor stub
}

//Operator functions
Node& Node::operator=(const Node& n) {
    if (this != &n) {
        ID = n.ID;
            x = n.x;
            y = n.y;
        seqNeighbours.clear();
        seqNeighbours = n.seqNeighbours;
        nodePrev = n.nodePrev;
    }
    return *this;
}

//Get&Set
int Node::getID() {
    return this->ID;
}

//Public member functions
void Node::addNeighbour(Node& n) {
    seqNeighbours.push_back(n);
}

double Node::distanceTo(Node& n) {
    return sqrt((n.x-x)*(n.x-x) + (n.y-y)*(n.y-y));
}

bool Node::isSeqNeighbour(int ID) {
    for (int i = 0; i < seqNeighbours.size(); i++) {
        if (seqNeighbours[i].getID() == ID) {
            return true;
        }
    }
    return false;
}

int Node::updateSeqNeighbours() {
    if (nodePrev == NULL) {
        return 1;
    } else {
        Node seed = *nodePrev;  //previous node as seed
        seqNeighbours.push_back(seed);

            for (int i = 0; i < 3; i++) {
                    if (seed.nodePrev == NULL) break;
                    double minDist = 15353453;
                    Node closest;
                    for (int j = 0; j < seed.seqNeighbours.size(); j++) {
                            double dist = distanceTo(seed.seqNeighbours[j]);
                            if (dist < minDist) {
                                    minDist = dist;
                                    closest = seed.seqNeighbours[j];
                            }
                    }
                    if (minDist < 150) {
                            seqNeighbours.push_back(closest);
                    }
                    seed = closest;
            }
            cout << "neighbours = " << seqNeighbours.size() << endl;
    }
    return 0;
}

void Node::_setDefaults() {
    x = 0;
    y = 0;
    ID = count;
    nodePrev = NULL;
    seqNeighbours.clear();
    count++;
}
#endif /* GRAPH_NODE_H_ */

Graph:图形:

#ifndef GRAPH_GRAPH_H_
#define GRAPH_GRAPH_H_

#include <vector>
#include <iostream>
#include "Node.h"

using namespace std;

class Graph {
public:
    Graph();
    virtual ~Graph();

    vector<Node> list;

    void addNode(Node& n);
    void addSeqNode(Node& n);


private:
    void _setDefaults();
};

Graph::Graph() {
    // TODO Auto-generated constructor stub

}

Graph::~Graph() {
    // TODO Auto-generated destructor stub
}

void Graph::addNode(Node& n) {
    list.push_back(n);
}

void Graph::addSeqNode(Node& n) {
    if (!list.empty()) {
        n.nodePrev = &list.back();
    }
    n.updateSeqNeighbours();
    list.push_back(n);
}

void Graph::_setDefaults() {
    list.clear();
}


#endif /* GRAPH_GRAPH_H_ */

I suspect running out of memory causes this.我怀疑内存不足会导致这种情况。 However 40 nodes with each 4 neighbours doesn't sound much of a problem to me.然而,每 4 个邻居有 40 个节点对我来说听起来没什么问题。 Anyone any idea what goes wrong?任何人都知道出了什么问题?

Edit: Error in german, so I need to guess: An exception accured in project prSimulation1.exe of class std::bad_alloc.编辑:德语错误,所以我需要猜测:在类 std::bad_alloc 的项目 prSimulation1.exe 中发生异常。 Adress of Exception: '0x5476016'.异常地址:'0x5476016'。 Process was stopped.进程已停止。

Your seqNeighbours is vector<Node> .您的seqNeighboursvector<Node> That means it stores the neighbours themselves, not pointers to them or their indices.这意味着它存储邻居本身,而不是指向它们或其索引的指针。 The copy constructor, therefore, copies all the neighbours.因此,复制构造函数复制所有邻居。 Copying each neighbour, in turn, requires to copy its neighbours , which requires to copy their neighbours, and so on.反过来,复制每个邻居需要复制它的邻居,这需要复制他们的邻居,依此类推。 Your assignment also copies all the neighbours, which requires to copy their neighbours, and so on.您的作业还复制所有邻居,这需要复制他们的邻居,依此类推。 This means that each copy exponentially increases memory load, until the system is unable to store all the neighbours, neighbours of neigbours etc.这意味着每个副本都会成倍增加内存负载,直到系统无法存储所有邻居、邻居的邻居等。

PS: on a side note, a vector called "list" is a bad idea. PS:附带说明,称为“列表”的向量是个坏主意。 It is like a list called "vector", a set called "map", or a cat called Dog.它就像一个叫做“vector”的列表,一个叫做“map”的集合,或者一只叫做 Dog 的猫。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM