2014-10-27 72 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