当前位置: 首页 > news >正文

js 死循环代码debug

最近在学习vuejs设计与实现的编译器

忧虑

在代码里面有大量的while这样的状态机,一不小心就会出现死循环。这让我非常的忧虑。


我当下的问题是:

  • 如何在遇到死循环时候,及时中断
  • 如何在遇到是循环的时候,可以定位到时那个函数出问题
  • 如何在不影响原代码【逻辑】的情况下(非不新增代码,而是不影响原来代码的逻辑),中断改死循环

我在想一个问题

        能否可以捕获到【死循环】。在检测到有死循环的时候,主动中断程序,并报告当前的死循环的程序的函数的名字。

        这里的捕获是在不影响原代码的情况下,可以监听到死循环,并主动中断,并暴露死循环的函数名字。

        当时经过几次尝试,例如给程序再包裹一个函数或注入代码,我发现好像都有些不大如意的地方。

        嗯,那如果抽离这个检测死循环的代码到独立函数,且让有while的程序自己调用,是否就可以一定层度的减少心智压力以及更好的debug呢?

函数名字

首先,我们需要得到运行函数的名字,js并没有提供这样的功能,但是函数的arguments.callee却可以拿到整个函数内容的文本

例如

function a(){
//dosome
 console.log(arguments.callee.toString())
}

执行代码a()后打印出来的内容是

得到的就是字符串

'function a(){
//dosome
 console.log(arguments.callee.toString())
}'

弊端

但是这有个弊端,如果代码是匿名函数,就拿不到函数名字,例如下面这样的代码,虽然复制给了变量a,但是函数本身是匿名函数

var a=function (){
//dosome
 console.log(arguments.callee.toString())
}

因为函数是个匿名函数,得到的字符串如下,这种情况就需要用户自己传递过来了

'function(){
//dosome
 console.log(arguments.callee.toString())
}'

正则

那我们可以使用正则拿到函数名字

let str = arguments.callee.toString();

var re = /^function\s*(\w+)\(/ig;

var matches = re.exec(str);

let fnName = matches[1];



死循环的特征是什么?


一个函数一直的不断的执行!!

如何判断呢?


如果在n秒内不断的执行某个函数那就可以认为他是死循环
我们可以用两个时间的间隔来判断这个函数执行了多久,如果大于某个时间,就让他break;


分解


那确定了方案后开始,对这个抽离的函数进行分解

  • 需要维护开始时间,结束时间
  • 需要更新结束时间
  • 需要为何死亡时间
  • 需要提供判断是否时死循环的函数


实现代码如下:
 

  var deadLoopCatch = function(argument, runFnName, deadLoopTimeLimit = 5000) {
            let fnName;
            if (runFnName) {
                fnName = runFnName;
            } else {
                let str = argument.callee.toString();
                var re = /^function\s*(\w+)\(/ig;
                var matches = re.exec(str);
                if (matches && matches[1]) {
                    fnName = matches[1];
                } else {
                    //如果是匿名函数,且用户没有传递第二个参数的时候,警告
                    console.warn("When the loop is an anonymous function, please pass the second parameter for function deadLoopCatch")
                    fnName = "---UMKNOW--";
                }


            }
            //初始化开始时间和结束时间
            let startTime = endTime = new Date().getTime();
            let result = {
                fnName,
                _startTime: startTime,
                _endTime: endTime,
                _deadLoopTimeLimit: deadLoopTimeLimit,
                updateTime: () => {
                    result._endTime = new Date().getTime();

                },
                isDeadLoop: () => {
                    let isDeadLoop = result._endTime - result._startTime >= result._deadLoopTimeLimit;
                    //这代码好像有一点弊端,如果这里不执行的话,还是会死循环
                    console.log("deadLoopCatch:result._endTime - result._startTime", result._endTime - result._startTime)
                    if (isDeadLoop) {
                        console.error(`Function ${fnName} triggered an endless loop!`)
                    }
                    return isDeadLoop;

                }
            }
            return result;
        }

一般情况下while不会执行耗时操作,所以如果一个while执行超过5秒,我们认为他就是死循环了,当然这个时间可以根据自己的实际情况调整


代码使用:

var abc = function(a, b, c) {
            var i = 1;
            let deadLoopCatchInit = deadLoopCatch(arguments, 'abc', 1000);
            while (true) {
                deadLoopCatchInit.updateTime()
                if (deadLoopCatchInit.isDeadLoop()) {
                    console.warn("强制中断", deadLoopCatchInit)
                    break;
                }
                console.log("执行中....")
            }
        }
        abc()

另外一个方案

        另外个简单debug方式,就是在while第一行使用console.log(“函数名字”) 这种方式也可以定位到死循环是哪一个代码,但是却无法避免死循环。


 

相关文章:

  • 微服务应用性能分析实战20 能力进阶:APM 工具自燃?随时客串 APM 工程师
  • 1、设计模式概述
  • 项目内置Express服务器解决Axios发送POST请求mock数据报404错误问题[Vue.js项目实践: 新冠自检系统]
  • Pytorch搭建自定义神经网络
  • Python数据分析——基础数据结构
  • TestNG-常用注解介绍
  • STM32时钟系统和TIMER配置(溢出中断/PWM)实例
  • 随想录一刷Day04——链表
  • 【javaweb简单教程】2.JSP实现数据传递和保存(含四大作用域及简单示例)
  • 7.ROS2笔记-节点
  • 【C++】类和对象(下篇)(万字)
  • 【牛客 - 剑指offer】JZ67 把字符串转换成整数 Java实现
  • python采集火热弹幕数据并做词云图可视化分析
  • 【小程序从0到1】模版与配置|数据绑定|事件绑定
  • NetSuite SuiteQL Query Tool
  • [PHP内核探索]PHP中的哈希表
  • canvas绘制圆角头像
  • Java读取Properties文件的六种方法
  • Java深入 - 深入理解Java集合
  • Laravel 中的一个后期静态绑定
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • React+TypeScript入门
  • vue学习系列(二)vue-cli
  • 利用DataURL技术在网页上显示图片
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • ​io --- 处理流的核心工具​
  • #{}和${}的区别?
  • #14vue3生成表单并跳转到外部地址的方式
  • (27)4.8 习题课
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (第二周)效能测试
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (三)mysql_MYSQL(三)
  • (循环依赖问题)学习spring的第九天
  • (原創) 未来三学期想要修的课 (日記)
  • (转)LINQ之路
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .NET6实现破解Modbus poll点表配置文件
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试
  • .net反混淆脱壳工具de4dot的使用
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题
  • [20170713] 无法访问SQL Server
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [2669]2-2 Time类的定义