C# 为什么我的C代码会导致堆栈溢出
这是导致堆栈溢出的代码,它只发生了大约一半的时间,我不知道它为什么会这样做。从我所看到的情况来看,只有当COM(TopCom等)有大量的数字时才会发生这种情况,所以大约5+左右,然后堆栈溢出C# 为什么我的C代码会导致堆栈溢出,c#,unity3d,C#,Unity3d,这是导致堆栈溢出的代码,它只发生了大约一半的时间,我不知道它为什么会这样做。从我所看到的情况来看,只有当COM(TopCom等)有大量的数字时才会发生这种情况,所以大约5+左右,然后堆栈溢出 public bool getConnected(int d) { if (topCom.connection != null) { if (d != topCom.connection.id) { if (topCom.connection.id == 0)
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;
}
这发生在递归函数中,您没有结束递归的基本条件。基本上一直调用该函数,直到达到堆栈溢出。。追踪你的代码,找出它为什么不断地调用自己 事实上,这里的人不能真正知道你想要完成什么,这是一种代码味道 其中很大一部分原因是,代码中有大量嵌套。正如您现在发现的,嵌套条件增加了调试代码的难度。此外,您可以轻松地组合一些条件-任何顶级分支中的所有条件实际上都可以组合成一条语句,如下所示:
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;
就我所能想象的,没有必要让单独的条件分支执行相同的函数,例如if(a){return true;}或者if(b){return true;}。只需将逻辑从else if移到原始if条件
但是,我建议将这些逻辑的一部分或全部封装到一个单独的函数中,因为您似乎在每个连接上执行相同的逻辑。您可以创建如下函数:
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=值;
}
}
这通常会导致堆栈溢出,很可能您在包含的代码范围之外引入了某种递归。您是否尝试调试代码?我们甚至不知道您的结构的定义-我们所知道的是,是的,代码可能会以无限循环结束(当当前实例和一个
topCom
形成循环时)-我无法给出一个合理的解决方案,除了传递一个带有已访问节点的HashSet
,以便您可以检测loops。在过去的四个小时里,我一直在使用堆栈跟踪和调试语句。我只是试图清理代码以进行显示。然后您必须重新考虑您的算法(我们对此一无所知)-您必须找到某种方法来打破图形中的循环-我告诉过您一种可能性(使用访问节点的哈希集)但是应该一直到它为真或为假,然后追溯到上,或者我的堆栈跟踪有一半的时间是这样说的。如果我理解你说的,如果做一个返回中间函数,它会一直在函数中运行?是的,但是它会给出一个大的NullReferenceException。编写预编辑不应该给出NullReference异常,除非我犯了错误。and(&&&)运算符的一个重要方面是,如果它在任何特定范围内遇到一个错误语句,它将停止操作,因此语句a!=null&&a!=12将永远不会抛出NullReferenceException,因为如果a为null,将永远不会检查!=12。