unity工程运行一段时间堆栈溢出,unity崩溃fatal error in GC. stack overflow

– 在这里做一下标记,困扰了我一天的难题,就是栈溢出导致软件奔溃的问题,gc报错,堆栈溢出.代码问题,没有指出具体溢出位置,需要自己慢慢排查.(多个个脚本大量的代码排查起来很艰难,首先要抓住的重点位置: 1.使用whiletrue的地方 2.使用递归的地方 3.在updata里不断实例化,new对象的地方. 4.updata里有数组list的地方 5.使用for循环赋值的地方(循环长度和赋值长度不一致时会导致for循环变成死循环,出现栈溢出))

导致堆栈溢出的原因:

一、局部数组过大。当函数内部的数组过大时,有可能导致堆栈溢出。
二、递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。
三、指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。

问题出现的地方:

我的工程里用到了udp的连接,数据传输.以及传输对于服务器返回的json字符串的解析,并使用了list接收解析的数组.并且使用了断网重连的机制,不断的inint初始化连接.

  • 我认为导致堆栈溢出的原因就是在于updata里面不断的初始化连接服务器,因为在udp连接服务器传输的方法里面有个whiletrue方法,不断的接收发送来的消息,并且还有一个new对象,新建一个线程.防止阻塞.
  • 1.当这两个方法都处在update的方法里不断的执行时,会导致在循环里不断的new新的对象,新建线程
  • 2.当while true方法在update里运行时会不断的重复方法,形成死循环.导致栈溢出.
  • 3.还有一点,在updata里不断的new list数组对象,导致大量的对象被新建,容易导致栈溢出.
我的解决办法:
  • 1.把updata里重连服务器的方法( inint() )放在了外面,因为该方法里面包括了whiletrue方法,并且还有一个new 线程的方法,如果一直在updata里执行,会出现嵌套死循环,以及大量线程.
  • 2.把updata里数new list的数组在方法的结束,进行了清空,list.clear(),或者list=null;l两者的区别:clear后该list还存在,null后不存在,被gc回收.个人建议设为null.就算在updata里不断的new出来,也会提醒后台gc及时的对该list进行回收.

总结

  • 1.对于数组,注意for循环的长度和数组的长度是否一致,如果不一致,很容易导致堆栈异常.
  • 2.死循环,对于死循环的使用要注意,比如递归的使用,容易堆栈溢出.更要注意嵌套的死循环,很容易堆栈溢出.在我的工程里我猜测时因为在updata里不断的执行死循环导致的.
  • 3.注意在for循环或者updata里出现不断的new对象,大量的对象被new出来后不确定被及时回收,在for循环结束之后要注意对于数组的清空,list.clear(),或者list=null.
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Stack 是一种特殊的线性表,它仅允许在线性表的末端(称为栈顶)进行插入和删除操作,又称为后进先出(LIFO)结构。在Unity中,可以使用Stack类来实现堆栈的功能。下面是一段使用Unity编写的堆栈的代码:Stack<int> stack = new Stack<int>(); stack.Push(1); // 入栈 stack.Push(2); // 再次入栈 int x = stack.Pop(); // 出栈,x=2 int y = stack.Pop(); // 再次出栈,y=1 ### 回答2: 使用Unity写一个堆栈(Stack)数据结构的代码示例如下: ```csharp using UnityEngine; public class StackExample : MonoBehaviour { private Stack<int> stack; void Start() { // 初始化堆栈 stack = new Stack<int>(); // 向堆栈中添加元素 stack.Push(1); stack.Push(2); stack.Push(3); // 获取堆栈顶部元素但不移除 int topElement = stack.Peek(); Debug.Log("栈顶元素为:" + topElement); // 移除并返回堆栈顶部元素 int poppedElement = stack.Pop(); Debug.Log("弹出的元素为:" + poppedElement); // 判断堆栈是否为空 bool isEmpty = stack.Count == 0; Debug.Log("堆栈是否为空:" + isEmpty); // 清空堆栈 stack.Clear(); // 再次判断堆栈是否为空 isEmpty = stack.Count == 0; Debug.Log("清空堆栈后,堆栈是否为空:" + isEmpty); } } ``` 这段代码使用Unity中的泛型堆栈(Stack)实现了一个简单的堆栈数据结构示例。首先,我们初始化堆栈,并通过`Push`方法向堆栈中压入元素1、2、3。然后,我们使用`Peek`方法获取堆栈顶部元素但不移除,并使用`Pop`方法移除并返回堆栈顶部元素。接着,我们通过`Count`属性判断堆栈是否为空,并使用`Clear`方法清空堆栈。最后,再次判断堆栈是否为空。通过运行以上代码,我们可以在Unity控制台中看到堆栈操作的结果。 ### 回答3: 在Unity中实现堆栈的代码可以利用List<T>数据结构来模拟堆栈的特性。下面是一个例子: 1. 首先,在Unity中创建一个C#脚本文件,比如命名为StackExample.cs。 2. 在脚本中定义一个List<T>类型的变量来表示堆栈,以及一些操作堆栈的方法。 ```C# using UnityEngine; using System.Collections; using System.Collections.Generic; public class StackExample : MonoBehaviour { private List<int> stack; void Start () { stack = new List<int>(); // 初始化堆栈 } void Update () { if (Input.GetKeyDown(KeyCode.Space)) { Push(Random.Range(1, 10)); // 按下空格键将随机数入栈 } if (Input.GetKeyDown(KeyCode.Return)) { Pop(); // 按下回车键将元素出栈 } } void Push(int value) { stack.Add(value); // 在堆栈顶部添加元素 Debug.Log("Push: " + value); } void Pop() { if (stack.Count > 0) { int value = stack[stack.Count - 1]; // 获取堆栈顶部元素 stack.RemoveAt(stack.Count - 1); // 从堆栈中删除顶部元素 Debug.Log("Pop: " + value); } else { Debug.Log("Stack is empty"); } } } ``` 上述代码实现了一个堆栈的基本功能,按下空格键时,会将一个随机数入栈;按下回车键时,会将堆栈顶部的元素出栈。运行后,在Unity编辑器的控制台中可以看到入栈和出栈的动态过程。 希望以上回答能对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值