2017-05-25 12 views
-2

私は4つの頂点の循環グラフを持っています。セグメンテーションフォルト(コアダンプ)エラーC++再帰呼び出し

各ノードは、nodelabelというマップに格納されているエッジに関連付けられています。

私はソースノード(オフセット0からノードサイズ)までの長さの深さのパスを与えるprintAll(int source、int depth)を呼び出そうとしています。

深度が650までは正常に動作しています。私がprintAll(2、800)を与える瞬間、それはセグメンテーションフォールトを与えています。

私は、エラーがprintAllPathsUtil関数から来ていることをデバッグしました。なぜ誰かがセグメンテーションフォルトが起こっている理由を指摘できますか? ?

Graph g(4); // 4 nodes 
g.addEdge(0, 1); 
g.addEdge(0, 2); 
g.addEdge(2, 0); 
g.addEdge(2, 3); 
g.addEdge(3, 3); 

g.addLabel(0, "AAGT"); 
g.addLabel(1, "CCTC"); 
g.addLabel(2, "TTCC"); 
g.addLabel(3, "CTC"); 
map < int, string > nodelabel; // Map containing Nodelabel corresponding to every node id 
void Graph::addLabel(int v, string s) { 
    nodelabel[v] = s; // Add w to v’s list. 
} 

void Graph::printAllPaths(int source, int depth) { 
    string kmerpath; 
    int * path = new int[V]; 
    int path_index = 0; // Initialize path[] as empty 

    // Call the recursive helper function to print all paths 
    for (int offset = 0; offset < nodelabel[source].length(); offset++) { 
    printAllPathsUtil(source, offset, depth, path, path_index, kmerpath, 1); 
    path_index = 0; 

    } 
} 

void Graph::printAllPathsUtil(int u, int offset, int d, int path[], int & path_index, string kmerpath) { 
    path[path_index] = u; // store Current node in the path[] 
    path_index++; 

    if (d == 0) { 
    //cout << kmerpath << endl; 
    } else if ((nodelabel[u].length() - offset) >= d) { 
    kmerpath.append(nodelabel[u].substr(offset, d)); 
    printAllPathsUtil(u, offset, 0, path, path_index, kmerpath); 
    } else // If current vertex is not destination 
    { 
    // Recur for all the vertices adjacent to current vertex 
    list <int> ::iterator i; 
    kmerpath.append(nodelabel[u].substr(offset, (nodelabel[u].length() - offset))); 
    for (i = adj[u].begin(); i != adj[u].end(); ++i) { 
     printAllPathsUtil(* i, 0, (d - (nodelabel[u].length() - offset)), path, path_index, kmerpath); 
    } 
    } 
    path_index--; // Remove current vertex from path[] 

} 
+1

あなたはC++でプログラムして、あなたが書いたものです。それではなぜあなたはCとして質問にタグを付けましたか? CとC++は同じ言語ではないので、混同しないでください。 – Rakete1111

+0

申し訳ありません。私はCの知識を持つ人もこの点で私を助けることができると思った。 – rombi

+2

@rombi _ "誰かがセグメンテーションフォルトが起こっている理由を私に指摘できますか?" _スタックオーバーフロー?再帰を使用すると、その可能性が最も高いです。ループと 'std :: stack'を使って再帰を置き換えてみてください。 –

答えて

0

再帰とループを使用すると、必ずしも明確でない場合があります。再帰はしばしばより複雑であると考えられ、スレッドプログラミングの安全性を目的とした関数型プログラミングに頻繁に関連しています。ただし、再帰が深すぎると、スタックメモリが不足することがあります。

char* foo() 
{ 
    char a[100000]; 
    memset(a, 0, 100000); 
    return a; 
} 

プログラムは、それが(100,000バイト、プラスの指示のために少し)呼び出されたときに、それに割り当てるメモリの量を知っている:

は、あなたが簡単な関数があるとしましょう。あなたはどこか別の場所からfoo()を呼び出す場合

char bar() 
{ 
    char* c = foo(); 
    char b = 1; 
    return c[0] + b; 
} 

は、その後、プログラムはbar()からfoo()プラスbar()のために少しのためのメモリを割り当てることを知っています。

char bar() 
{ 
    if (condition) 
    { 
    return foo() + bar(); 
    } 
    else return 0; 
} 

しかし、あなたはbar()再帰作れば、それはそれは行く回数深いの任意のアイデアを持っていないため、プログラムが実際に割り当てるためにどのくらい知っていません。これは合理的な推測ですが、推測でサポートされていた深さを超えると、スタックのオーバーフローが発生します。 excessibly深い行くとき

解決策ではなく、ループにある:

char bar() 
{ 
    char* a; 
    while (condition) 
    { 
    a += foo(); 
    } 
    return a; 
} 

この場合、私たちは私たちのデザインのfunctional側面を失うが、我々は一度に一回foo()を呼び出すので、メモリが再び解放されますループをリセットする度に

この説明が有用であり、正しいことを願っています。私は機能があまり意味がないことを知っていますが、うまくいけばあなたにアイデアを与えます。

関連する問題