2017-05-25 142 views
-2

我有一個4個頂點的循環圖。分割錯誤(核心轉儲)錯誤C++遞歸調用

每個節點都與我存儲在名爲節點標籤的映射中的邊相關聯。

我想調用printAll(int source,int depth),它會給我從源節點(偏移量0到節點大小)的長度深度路徑。

當深度達到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

對不起。我認爲有這方面知識的人也可以幫助我。 – rombi

+2

@rombi _「任何人都可以指出我發生分段錯誤的原因嗎?」_堆棧溢出?如果使用遞歸,那很可能。嘗試用循環和'std :: stack'替換遞歸。 –

回答

0

有時,當您使用遞歸與循環時,並不總是很清楚。遞歸通常被認爲更復雜,並且經常與函數式編程相關,旨在非常安全。但是,如果你在遞歸中太深入,你可能會很快耗盡堆棧內存。

比方說,你有一個簡單的功能:

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

程序知道多少內存分配給它時,它被調用(100,000字節,再加上一點點的說明)。

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

,如果你從別的地方調用foo(),則程序知道分配內存爲foo()bar()再加上一點點的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()一次,所以內存再次釋放每次我們重置循環。

我希望這個解釋有幫助和正確。我知道這些功能沒有什麼意義,但希望如果給你的想法。