zoukankan      html  css  js  c++  java
  • 破败之王杀人戒bug原理剖析(从底层存储来解释)

    今儿看到了破败之王的bug,一级团杀了人变成了对面,然后送塔,戒指就变成了很夸张的层数。

    视频如下:

    https://www.bilibili.com/video/BV1yr4y1A7Mo

    一开始我也只是觉得好夸张啊,这什么玩意儿。但是看到杀人戒的层数,瞬间就大概明白怎么回事了。

    下面粗略说一下思路,可能不对,但是原理应该差不多。

    先看看戒指层数:

     

    65534!学计算机的可能立马就会想到2的16次方,也就是65536。

    众所周知,计算机中的数据都是用二进制表示的,杀人戒的层数肯定也是用的一个二进制的值表示的。而根据65534这个数字,基本可以断定这个值用的是16bit的内存来记录的。

    如果是1层杀人戒,内存里存的就会是:

    0000000000000001,16位,最后一位是1。

    2层的呢,就是

    0000000000000010。

    这个二进制表示我就不多做赘述了,大家感兴趣的可以查一下。

    这个视频里,是破败之王击杀了牛头,戒指本应该是+2的,但是却变成了65534,那么65534在内存中怎么表示的呢?

    1111111111111110。

    这时候就要引入另一个概念了,补码。前面所说的都是原码,是不能表达负数的。而表达负数,就要用补码了。这个具体原理这里也不引申了,就是一种 内存字节 ->实际值的表达方式。

    65534用原码表示是1111111111111110,而1111111111111110这一坨二进制内存,如果用补码表示,它代表的值就是-2!

    这个就是关键了!65534和-2在不同的编码方式中,所对应的二进制是一样的。

    再想一下杀人戒的属性,杀人应该是+2的,但是此时破败之王变成了敌方单位,是不是这里的代码有bug,将+2就给算成了-2?

    然后算戒指层数的时候,程序员用的是补码,-2就是1111111111111110。

    而读取戒指层数时,另一个程序员却用了原码,1111111111111110就读取成了65534(原码和补码在表示比较小的正数时是完全一样的,所以正常情况下戒指层数也不会读错)。

    这样就完全对的上了。。

    溢出了的话不应该是65534,出现65534应该就是我描述的这样了,程序本身有bug,原码和补码也用混了。

    csonezp@gmail.com
  • 相关阅读:
    86. Partition List
    2. Add Two Numbers
    55. Jump Game
    70. Climbing Stairs
    53. Maximum Subarray
    64. Minimum Path Sum
    122. Best Time to Buy and Sell Stock II
    以场景为中心的产品设计方法
    那些产品经理犯过最大的错
    Axure教程:如何使用动态面板?动态面板功能详解
  • 原文地址:https://www.cnblogs.com/csonezp/p/14485814.html
Copyright © 2011-2022 走看看