
没想到吧,就是这么简单几行代码,直接干趴B站两三个小时,搞得B站程序员彻夜无眠 头发狂掉。 你可能会问,这不就是个普普通通用来求最大公约数的函数吗,怎么就有如此大的威力? 背后一桩桩一件件,归根结底其实就一句话:0,它真的不兴除啊。 具体详情,咱们还是一起来看看“事故报告”。 字符串“0”引发的“血案” 先来说道说道引发惨案的根本原因,也就是开头贴出的这个 gcd函数 。 学过一点编程知识的小伙伴应该都知道,这是一种用 辗转相除法 来计算最大公约数的 递归函数 。 跟我们手算最大公约数的方法不同,这个算法是酱婶的: 举个简单的例子,a=24,b=18,求a和b的最大公约数; a除以b,得到的余数是6,那么就让a=18,b=6,然后接着往下算; 18除以6,这回余数是0,那么6也就是24和18的最大公约数了。 也就是说,a和b反复相除取余数,直到b=0,函数中: if b==0 then return a end if b==0 then return a end 这个判断语句生效,结果就算出来了。 基于这样的数学原理,我们再来看这段代码,似乎没什么问题: 但如果输入的b是个字符串“0”呢? B站的技术解析文章中提到,这段出事的代码是用Lua写的。Lua具有这么几个特点: 这是一种动态类型语言,常用习惯里变量不需要定义类型,直接给变量赋值就行。 Lua在对一个数字字符串进行算术操作时,会尝试将这个数字字符串转成一个数字。 在Lua语言中,数学运算n%0的结果是nan (Not A Number) 。 我们来模拟一下这个过程: 1、当b是一个字符串“0”时,由于这个gcd函数没有对其进行类型校验,因此在碰上判定语句时,“0”不等于0,代码中“return _gcd(b, a%b)”触发,返回_gcd(“0”, nan)。 2、_gcd(“0”, nan)再次被执行,于是返回值变成了_gcd(nan, nan)。 这下就完犊子了,判定语句中b=0的条件永远没法达到,于是, 死循环 出现了。 也就是说,这个程序开始疯狂地原地转圈,并且为了一个永远得不到的结果,把CPU占了个100%,别的用户请求自然就处理不了了。 那么问题来了,这个“0”它到底是怎么进去的呢?…
阅读更多(Read More)