调试分段错误是我作为C ++初学者所面临的关键问题之一。我曾尝试在以下代码行中使用C ++ STL实现有向图中的深度优先搜索(基于Steven Skienna的算法设计手册):
#include <iostream>
#include <list>
#include <cstdio>
using namespace std;
#define TREE 0 /* tree edge */
#define BACK 1 /* back edge */
#define CROSS 2 /* cross edge */
#define FORWARD 3 /* forward edge */
class Graph
{
int V; //no of vertices
int time;
list <int> *adj; //Pointer to an array containeing the adjacency list
public:
Graph(int V); //A constructor
int entry_time[] ,exit_time[] , parent[] ;
bool processed[] , discovered[] ;
void addEdge(int v , int w ) ; // a function to add an edge to graph
void DFS(int v); // print DFS transversal of the complete graph
void initializeGraph () ; // a function used by DFS
void process_edge(int x , int y);
void process_vertex_early(int x);
void process_vertex_late(int x);
int edge_classification(int x , int y);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V]; // dynamic allocation of V lists to an array named adj
}
void Graph::addEdge(int v, int w )
{
adj[v].push_back(w); //Add w to v's list
}
void Graph::initializeGraph ()
{
time = 0;
for (int j=0;j<V;j++)
{
processed[j]=discovered[j] = false;
parent[j]=-1;
}
// Recur for all the vertices adjacent to this vertex
}
void Graph::DFS(int v)
{
process_vertex_early(v);
list <int>::iterator i ;
for (i=(adj[v].begin());i!=adj[v].end();++i)
{ cout << *i ;
if (discovered[*i]==false)
{
parent[*i] = v ;
process_edge(v,*i);
DFS(*i);
}
else if (processed[*i]==false)
process_edge(v,*i);
}
process_vertex_late(v);
}
void Graph::process_vertex_early(int v)
{
discovered[v] = true;
time = time +1 ;
entry_time[v] = time ;
printf("discovered vertex %d at time %d\n",v, entry_time[v]);
}
void Graph::process_vertex_late(int v)
{
time = time + 1 ;
exit_time[v] = time;
processed[v] = true;
//printf("processed vertex %d at time %d\n",v, exit_time[v]);
}
int Graph::edge_classification (int x , int y )
{
if (parent[y]==x) return (TREE);
if (discovered[y] && !processed[y]) return (BACK);
//cout << " Warning : self loop " << x << y ;
}
void Graph::process_edge(int x , int y)
{
int type ;
type = edge_classification(x,y);
//if (type== BACK) cout << "Back Edge" << x << " -> " << y << endl;
//else if (type== TREE) cout << "Tree Edge" << x << " -> " << y << endl;
//else cout << " Not in the type " ;
}
int main()
{
Graph g(4);
g.initializeGraph();
g.addEdge(0,1);
g.addEdge(0,2);
g.addEdge(1,2);
g.addEdge(2,0);
g.addEdge(2,3);
g.addEdge(3,1);
cout << " Following is a DFS transversal \n " ;
g.DFS(0);
return 0;
}
在搜索操作达到一个或两个深度后发生分段错误。我曾尝试使用类似的语法来应用广度优先搜索。请帮我调试这段代码。谢谢。
答案 0 :(得分:3)
第一步是阅读所有编译器警告(并在打开警告的情况下编译)。
例如:
int entry_time[] ,exit_time[] , parent[] ;
这些数组的定义没有大小 - 但您要将数据放入其中。这意味着您在数组边界之外写入会导致未定义的行为(例如您看到的崩溃和双重释放)。像为adj
那样为这些数组分配空间,或者使用另一个容器(例如vector
),您可以根据需要调整其大小。
同样edge_classification
并不总是返回一个值 - 你的编译器应该警告过你。
修改:有关std::vector
您无法将数组声明为entry_time[V]
,因为在编译时不知道V
的值。您可以拥有许多不同大小的Graph
个对象。
如果您将数组更改为std::vector
,则可以在Graph
构造函数中分配它们的大小,让std::vector
类担心分配和释放内存。
例如:
在课程中将entry_time
声明为std:vector
:
std::vector<int> entry_time;
在构造函数中,设置entry_time
向量的大小。
entry_time.resize(V);
请注意,您可以在此处使用V
作为参数来调整大小,因为它在运行时已经有了值。
std::vector
具有类似于数组的普通访问器,因此您可以像对待数组一样将值分配给向量的条目。例如,您现有的代码仍然有效:
entry_time[v] = time ;