C++ std::vector::push_back抛出分段错误

C++ std::vector::push_back抛出分段错误,c++,vector,segmentation-fault,C++,Vector,Segmentation Fault,我的程序有问题。对于少量的边,它工作得很好,但当它得到15000条定向图的边时,我在运行一分钟后得到了分割错误。调试器说它是由向量push_-back方法抛出的。你们中有人知道代码有什么问题,以及如何避免它吗 在dfs过程的行结果处抛出错误。推回(tmpResult) #包括 #包括 #包括 使用名称空间std; 类型定义结构{ unsigned int endNode;//目标节点数 bool used;//如果在dfs中使用了edge,则为true }边缘型; 类型定义结构{ unsigne

我的程序有问题。对于少量的边,它工作得很好,但当它得到15000条定向图的边时,我在运行一分钟后得到了分割错误。调试器说它是由向量push_-back方法抛出的。你们中有人知道代码有什么问题,以及如何避免它吗

在dfs过程的行结果处抛出错误。推回(tmpResult)

#包括
#包括
#包括
使用名称空间std;
类型定义结构{
unsigned int endNode;//目标节点数
bool used;//如果在dfs中使用了edge,则为true
}边缘型;
类型定义结构{
unsigned int startNode;//源节点数
向量边;//从节点传出的边
}节点类型;
类型定义结构{
无符号整数起始节点;
无符号int-endNode;
}结果类型;
bool loadInput(向量和图形、无符号整数和numdges);
void dfs(向量和图形、无符号整数i、无符号整数numEdges、向量和结果);
int main(int argc,字符**argv){
矢量图;
矢量结果;
无符号整数numEdges;
结果:准备金(300000);
//生成定向多重图(3个节点,150000条边)
numEdges=150000;
节点类型tmpNode;
边缘型tmpEdge;
for(无符号整数i=0;i<50000;i++){
tmpEdge.used=false;
tmpEdge.endNode=1;
tmpNode.edge.push_back(tmpEdge);
}
tmpNode.startNode=0;
图形。推回(tmpNode);
tmpNode.edge.clear();
for(无符号整数i=0;i<50000;i++){
tmpEdge.used=false;
tmpEdge.endNode=2;
tmpNode.edge.push_back(tmpEdge);
}
tmpNode.startNode=1;
图形。推回(tmpNode);
tmpNode.edge.clear();
for(无符号整数i=0;i<50000;i++){
tmpEdge.used=false;
tmpEdge.endNode=0;
tmpNode.edge.push_back(tmpEdge);
}
tmpNode.startNode=2;
图形。推回(tmpNode);
tmpNode.edge.clear();

cout
dfs
递归地调用自身;增加
numEdges
会增加递归深度,因此,增加
numEdges
足以导致堆栈溢出(在您的平台上表现为segfault)


使用更大的堆栈大小(特定于编译器)构建程序,或者在这种情况下不使用递归。

dfs
递归调用自身;增加
numeges
会增加递归深度,因此,增加
numeges
足以导致堆栈溢出(在您的平台上显示为segfault)


或者使用更大的堆栈大小(特定于编译器)构建程序或者在这种情况下不要使用递归。

如果
push_back
抛出,很可能是因为您的程序内存不足。由于您没有捕获任何异常,将调用默认异常处理程序并终止应用程序。在gdb中,您可以使用
catch throw
命令在每次“抛出”时停止语句。

如果
push_back
抛出,很可能是因为您的程序内存不足。由于您未捕获任何异常,将调用默认异常处理程序并终止应用程序。在gdb中,您可以使用
catch throw
命令在每次“抛出”时停止语句。

很可能是递归太深,导致堆栈溢出。在大多数平台上,堆栈具有固定大小;您可以将其变大,但可能仍然无法支持任意大的图形


也许您可以用迭代算法替换递归,维护自己的堆栈(例如,a
std::stack
)返回时需要恢复的状态。那么图形大小的唯一限制是可用内存。

很可能是递归太深,导致堆栈溢出。在大多数平台上,堆栈具有固定大小;您可以将其变大,但可能仍然无法支持任意大的图形美国


也许你可以用一个迭代算法来代替递归,在回溯时维护你自己需要恢复的状态堆栈(例如
std::stack
)。那么图表大小的唯一限制就是可用内存。

你不能缩小范围吗?你不应该使用
graph[i]访问向量
。使用
图形更安全。at(i)
,因为这将首先检查图形是否足够大,如果现在出现异常,将引发异常。
[i]
的危险在于它可能试图访问数组边界以外的区域并损坏内存,从而导致seg错误或类似错误。有些人可能会认为
。at(i)
速度较慢,但忽略它们:-)在现实世界的程序中,您的配置文件通常会确认这一点可以忽略不计。在优化之前,请关注正确性。@Aaron:索引越界是一种编程错误,即错误。使用
.at()
而不是
运算符[]
不能修复错误,它只是让错误以不同的方式表现出来。建议是实际修复错误,而不仅仅是在遇到错误时抛出异常。@ildjarn,使用
。at
应该更容易找到错误。它创建定义的行为并有助于跟踪根本原因。但是
[]
是完全未定义的-一个向量上的越界错误可能会被静默地接受,并且在访问另一个向量之前不会引起任何问题,这会造成混乱。我建议两个步骤:首先,默认情况下在
处使用
,因为它将有助于显示错误和理解错误,其次是修复错误。@Aaron:这就是原因断言是为了——让程序员知道有一个bug——我使用的每个标准库都有一些在调试构建中启用边界检查断言的功能。用户不关心bug是如何表现出来的,只关心有一个bug,所以在mor中表现bug
#include <cstdlib>
#include <iostream>
#include <vector>

using namespace std;

typedef struct {
    unsigned int endNode;      // Number of dest node
    bool used;                 // true, if edge was used in dfs
} EdgeType;

typedef struct {
    unsigned int startNode;     // Number of source node
    vector<EdgeType> edge;      // Outgoing edges from node
} NodeType;

typedef struct {
    unsigned int startNode;
    unsigned int endNode;
} ResultType;


bool loadInput(vector<NodeType>& graph, unsigned int& numEdges);
void dfs(vector<NodeType>& graph, unsigned int i, unsigned int numEdges, vector<ResultType>& result);

int main(int argc, char** argv) {
    vector<NodeType> graph;
    vector<ResultType> result;
    unsigned int numEdges;

    result.reserve(300000);

    // Generate oriented multigraph (3 nodes, 150000 edges)
    numEdges = 150000;
    NodeType tmpNode;
    EdgeType tmpEdge;

    for (unsigned int i = 0; i < 50000; i++) {
        tmpEdge.used = false;
        tmpEdge.endNode = 1;
        tmpNode.edge.push_back(tmpEdge);     
    }
    tmpNode.startNode = 0;
    graph.push_back(tmpNode);
    tmpNode.edge.clear();

    for (unsigned int i = 0; i < 50000; i++) {
        tmpEdge.used = false;
        tmpEdge.endNode = 2;
        tmpNode.edge.push_back(tmpEdge);     
    }
    tmpNode.startNode = 1;
    graph.push_back(tmpNode);
    tmpNode.edge.clear();

    for (unsigned int i = 0; i < 50000; i++) {
        tmpEdge.used = false;
        tmpEdge.endNode = 0;
        tmpNode.edge.push_back(tmpEdge);     
    }
    tmpNode.startNode = 2;
    graph.push_back(tmpNode);
    tmpNode.edge.clear();

    cout << "numEdges: " << numEdges << endl;

    // Find way
    for (unsigned int i = 0; i < graph.size(); i++) {
        dfs(graph, i, numEdges, result);
    }

    // No way found
    cout << "-1" << endl;

    return 0;
}

void dfs(vector<NodeType>& graph, unsigned int i, unsigned int numEdges, vector<ResultType>& result) {
    // Way was found, print it and exit program (bad style, only for testing)
    if (numEdges == result.size()) {
        cout << graph.size() << endl;
        vector<ResultType>::iterator it;
        for (it = result.begin(); it != result.end(); it++) {
            cout << (*it).startNode << " " << (*it).endNode << endl;
        }
        cout << "0 0" << endl;
        exit(0);
    }
    // For each outgoing edge do recursion 
    for (unsigned int j = 0; j < graph[i].edge.size(); j++) {
        if (i >= graph.size()) return;
        if (!graph[i].edge[j].used) {
            graph[i].edge[j].used = true;
            ResultType tmpResult;
            tmpResult.startNode = graph[i].startNode;
            tmpResult.endNode = graph[i].edge[j].endNode;
            result.push_back(tmpResult);
            dfs(graph, graph[i].edge[j].endNode, numEdges, result);
            result.pop_back();
            graph[i].edge[j].used = false;
        }
    }
}