2014-10-27 147 views
-2

這是給出堆棧溢出的代碼,它只發生了大約一半的時間,我不知道它爲什麼這樣做。從我看到它只發生在Coms(TopCom等)的大量數字中,因此大約5+然後堆棧溢出。爲什麼我的C#代碼導致堆棧溢出

public bool getConnected(int d) { 
    if (topCom.connection != null) { 
     if (d != topCom.connection.id) { 
      if (topCom.connection.id == 0) { 
       return true; 
      } else if (topCom.connection.connected == true) { 
       if (Development.instance.currentDos.buttons[topCom.connection.id].getConnected(id)) { 
        return true; 
       } 
      } 
     } 
    } 

    if (leftCom.connection != null) { 
     if (d != leftCom.connection.id) { 
      if (leftCom.connection.id == 0) { 
       return true; 
      } else if (leftCom.connection.connected == true) { 
       if (Development.instance.currentDos.buttons[leftCom.connection.id].getConnected(id)) { 
        return true; 
       } 
      } 
     } 
    } 

    if (rightCom.connection != null) { 
     if (d != rightCom.connection.id) { 
      if (rightCom.connection.id == 0) { 
       return true; 
      } else if (rightCom.connection.connected == true) { 
       if (Development.instance.currentDos.buttons[rightCom.connection.id].getConnected(id)) { 
        return true; 
       } 
      } 
     } 
    } 

    if (botCom.connection != null) { 
     if (d != botCom.connection.id) { 
      if (botCom.connection.id == 0) { 
       return true; 
      } else if (botCom.connection.connected == true) { 
       if (Development.instance.currentDos.buttons[botCom.connection.id].getConnected(id)) { 
        return true; 
       } 
      } 
     } 
    } 

    return false; 
} 
+0

你試圖調試代碼。?我們甚至不知道你的結構的定義 - 我們知道的是,代碼可能以無限循環結束(當前實例ce和其中一個'topCom'形式*一個循環*) - 我不可能給出一個合理的解決方案,而不是將HashSet與*已經訪問的*節點一起傳遞,以便可以檢測循環 – Carsten 2014-10-27 05:08:16

+0

我一直在使用堆棧跟蹤和調試我剛剛嘗試清理顯示代碼的最後四個小時的聲明。 – Dillyo09 2014-10-27 05:15:30

+0

然後你必須重新思考你的算法(我們一無所知) - 你**必須找到某種方式來擺脫圖中的週期 - 我告訴過你一種可能性(使用訪問節點的HashSet) – Carsten 2014-10-27 05:32:13

回答

1

這發生在您沒有結束遞歸的基本條件的遞歸函數中。你基本上一直在調用這個函數,直到你到達堆棧溢出爲止。跟蹤你的代碼,並找出爲什麼它自稱無止境。

+0

但是應該走低谷,直到它真或假,然後追溯或在那個時候我的堆棧跟蹤說。 – Dillyo09 2014-10-27 05:17:04

+0

如果我明白你說什麼,如果做一個返回中功能它繼續通過函數? – Dillyo09 2014-10-27 05:22:06

1

事實上,這裏的人不能真正告訴你想要完成的是一種代碼味道的種類。

其中很大一部分是你的代碼中嵌套數量驚人。正如你現在發現的那樣,嵌套條件增加了調試代碼的難度。此外,你可以很容易地結合你的一些條件句 - 所有在任何頂級分支的條件句實際上可以合併成一個聲明,內容如下:

if ((topCom.connection != null && d != topCom.connection.id && topCom.connection.id == 0) || 
    (topCom.connection.connected == true && 
    Development.instance.currentDos.buttons[topCom.connection.id].getConnected(id))) 
{ 
    return true; 
} 

return false; 

至於我能想象,有沒有點具有執行相同功能的獨立條件分支,例如如果(a){return true; } else if(b){return true; }。如果有條件的話,只需將其他邏輯從原來的位置移到原始位置。

但是,我建議將這些邏輯的部分或全部封裝到一個單獨的函數中,因爲它看起來好像你在每個連接上執行相同的邏輯。你可以創建一個函數,像這樣:

public bool ConnectionIsValid(connectionObject // replace with the actual type) 
{ 
    if (topCom.connection != null && d != topCom.connection.id && topCom.connection.id == 0) 
     || (topCom.connection.connected == true 
     && Development.instance.currentDos.buttons[topCom.connection.id].getConnected(id)) 
     return true; 

    return false; 
} 

這樣你就可以接着只需調用ConnectionIsValid每個連接的設備,而不是使用條件語句上爲每個連接80的某些行。

在這段代碼中出現StackOverflowException似乎也值得懷疑。除非你有關於任何在此代碼引用的對象的循環引用(在這種情況下,有你使用一個setter訪問指定的值相同的變量像樣的機會: 對象A { 設置 { 這.A =值; }}

這總會引起堆棧溢出,很可能你已經介紹了某種遞歸的包括代碼的範圍之外

+0

是的,但它會給一個大的NullReferenceException遍佈整個地方。編寫預編輯 – Dillyo09 2014-10-27 05:26:09

+0

除非我犯了錯誤,否則不應該給出NullReferenceException。和(&&)運算符的一個重要方面是,如果它在任何特定範圍內遇到單個虛假語句,它就停止運行,因此語句A!= null && A!= 12永遠不會拋出NullReferenceException,因爲A!= 12將永遠不會被檢查應該是空的。 – furkle 2014-10-27 05:27:42