[英]how can i get catch the root of a stackoverflow exception on recursive code
我有以下遞歸代碼,我得到一個stackoverflow異常。 我無法弄清楚根本原因,因為一旦我得到異常,我在Visual Studio中得不到完整的調用堆棧。
這個想法是有組織團隊加入更大的“主要”團隊。
有沒有人看到下面這段代碼的缺陷可能是罪魁禍首?
private Unit GetUnit(Unit organisationalUnit)
{
if (organisationalUnit.IsMainUnit)
{
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
return GetUnit(organisationalUnit.Parent);
}
IsMainUnit
和Parent
的getter是否不調用GetUnit
。 root總是有Parent == null
嗎? 試過檢查
if (organisationalUnit.Parent == organisationalUnit)
return null;
?
你可以嘗試這個來更好地調試它。 它不會影響您的生產代碼。
using System.Diagnostics;
private Unit GetUnit(Unit organisationalUnit, int depth)
{
debug.assert(depth < 10, "Reached an unexpected high recursion depth");
if (organisationalUnit.IsMainUnit)
{
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
return GetUnit(organisationalUnit.Parent, depth + 1);
}
private Unit GetUnit(Unit organisationalUnit)
{
return GetUnit(organisationalUnit.Parent, 0);
}
第二個想法......
最有可能的是你在某處有一個循環引用。
A.parent = B;
B.parent = C;
C.parent = A;
您可以嘗試傳遞一組先前訪問過的節點,並檢查您之前是否訪問過此節點。
遞歸的事情是你必須確保它將結束 ,並且未經檢查的循環引用是不會結束的情況。
有沒有理由不將它重新編碼為迭代? 這樣,為了捕獲不良(循環)數據,更容易對組織樹的深度設置硬限制。
遞歸很有趣,尾部優化甚至可以使它高效,但在這里它看起來像一個小問題的大錘子。
我對視覺工作室了解不多。 但你應該檢查是否復發。 例如
private Unit GetUnit(Unit organisationalUnit)
{
GetUnit(organisationalUnit, new vector());
}
private Unit GetUnit(Unit organisationalUnit,vector x)
{
if (organisationalUnit.IsMainUnit)
{
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
x.add(this);
if(x.contains(organisationalUnit.Parent)) throw new Exception("recurrent parent");
return GetUnit(organisationalUnit.Parent,x);
}
一種方法是減少堆棧大小,以便它可以更早崩潰。
你可以通過在程序開頭浪費幀來實現這一點,即獲得如下的堆棧跟蹤:f_n,f_(n-1),...,f_1,廢物,廢物,......,廢物,如(在C偽代碼中)
int wasted = 1;
waste(int n,void(* f)()){if(n> 0)waste(n - 1,f)else f(); 浪費+ = 1; }
main(){waste(N,mainprime); }
mainprime是你的舊主力,N足夠大到達你想要的f_1。
代碼看起來不錯,也許你在單元樹中有一些封閉的循環? 嘗試使用organisationalUnit.GetHashCode值添加跟蹤線,跟蹤輸出不受限制,可以幫助檢測堆棧溢出原因。
我想你可以通過重寫這一點來避免遞歸
while(organisationalUnit!=null && !organisationalUnit.IsMainUnit)
organisationalUnit=organisationalUnit.Parent;
return organisationalUnit;
我希望有所幫助。
編輯:我剛剛意識到,如果你有某種循環依賴,這仍然會失敗。
您的圖表中可能有一個循環(請參閱,它不是樹)。
您可以使用這樣的代碼來檢測它:
private Unit GetUnit(Unit organisationalUnit) {
return GetUnit(organisationalUnit, new HashSet<Unit>());
}
private Unit GetUnit(Unit organisationalUnit, HashSet<Unit> visited) {
if (visited.Contains(organisationalUnit)) {
throw new Exception("Cycle detected!"); // or just return null if you prefer
}
visited.Add(organisationalUnit);
if (organisationalUnit.IsMainUnit) {
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
return GetUnit(organisationalUnit.Parent, visited);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.