(图片来源于网络)
2001年苹果公司发布第一代iPod,它的推出在当时引起了轰动,它拥有大容量存储空间和全新的操作方式,并且还非常漂亮(在当时看来),因此在市场上大受欢迎,苹果公司也因此赚的盆满钵满。
微软公司看到了个人播放器的前景,也想从这个市场分一杯羹,因此微软公司在2006年推出了第一代类似iPod的产品Zune。
虽然在个人电脑操作系统方面,windows操作系统占据了绝大多数份额,但是Zune却远不如创新不断的iPod销量高。Zune 在销量最高的时候也只是拿下了美国便携播放器市场份额 9%,远远低于 iPod 的 63%。销量惨淡不说,Zune的软件BUG又为苹果公司送了助攻。
2008年的最后一天,微软的30G存储版本Zune却遇到大规模无法启动问题。在这一天内,无论出于什么原因,只要用户重启了Zune,Zune就会卡在开机LOGO界面中无法启动。
互联网戏剧性的加剧了这个BUG的传播,因为大批网友在网上描述了这个问题,寻求解决方案,其它网友纷纷用自家Zune测试,成功的测试出只有30G存储版本Zune会遇到无法启动问题,顺带着大批设备变砖。
微软也是紧急出动,为了使事态不扩大而努力的工作着:先是发布公告称自己正在卖力的解决这个问题中,大家不必恐慌,会尽快通过Zune官方网站公布解决方案;随后,微软给出了问题原因和临时解决方案。
30GB存储版本Zune无法启动的原因在于Zune播放器的内置时钟驱动软件有BUG,使其无法正确处理闰年的最后一天(2008 年是闰年)!临时解决方案就一个字:等!你没看错,就是等。等到Zune电量耗尽关机,然后再等到2009年1月1日上午7点后,充电开机就能自然解决。
闰年BUG是比较常见的,究其原因,是瑞年不常见并且定义容易迷惑人引起的。不要小看了闰年,我们看一下闰年的定义,满足以下两个条件中任意一个的,为闰年:
    • 年份能被4整除,且不能被100整除
    • 能被400直接整除

你能从这个定义中写出一个正确的闰年判断方法吗?可以在私下试试,我们还是回过头来看微软Zune的时钟驱动BUG是怎么出现的。
微软30G存储版本Zune使用的时钟芯片是飞思卡尔的,有网友找到了该时钟驱动源代码,截取出错代码如下所示。 
该代码用于将日期(days)转换成年份。由于闰年有366天,而平年只有365天,所以要分别处理这两个年份逻辑。当循环处理到2008年时,程序在执行第3行if(DateTime.IsLeapYear(year))后,判断出2008年为闰年,然后执行第5行if(days > 366),软件BUG就出在这里!在2008年的最后这天,变量days中恰好是366,不能满足第5行的”days > 366”这个条件,然后程序转到第1行,然后执行第三行,再执行第5行,发现条件不成立再次执行第1行,如此死循环!

while(days > 365)
{
    if(DateTime.IsLeapYear(year))
    {
        if(days > 366)
        {
            days -= 366;
            year += 1;
        }
     }
     else
     {
        days -= 365;
        year += 1;
     }
}

编程无小事,任一点疏忽都会带来难以估量的损失!另外,这个BUG对我们的测试也很有启发,我想飞思卡尔和微软的开发人员一定详细的测试过这个代码,但他们都忽视了“润年最后一天”这个边界条件!这告诉我们验证逻辑时,切勿盲目自信,应重点关注那些不常使用的点上,往往这些点才是问题频频爆发的原因。
Zune随后的发展如何呢?2011年10月4日微软宣布,停止生产Zune,2013年11月22 Zune商店关闭,至此微软在个人播放器领域的尝试告一段落。这或许并不是微软的错,因为随着智能手机的普及,单独的便携式播放器的份额被智能手机严重蚕食,即便是苹果的iPod也逐渐成为了边缘产品,被归结到了“其它设备”类,想来离全面停产也不远了。
微软停止生产Zune后,在其它硬件领域有了新的突破,那就是微软surface系列,包括平板和笔记本,成为了Windows系统设备的标杆!

历史上的重大软件BUG启示录第9篇---微软的硬件尝试的更多相关文章

  1. JVM系列.历史上出现过的Java虚拟机

    HotSpot绝对是当今商用虚拟机的王者,但是在Java历史上出现过很多Java虚拟机,这篇文章就来整理下历史上出现过的Java虚拟机以及他们的特性. Sun Classic Sun Classic虚 ...

  2. 史上最臭名昭著五大软件Bug

    在现今数字年代,计算机bug不但困扰着每个程序员,更会无可避免影响我们的生活,小到每个人的衣食住行,大到国家经济,世界局势.随着我们的生活方式渐渐的数字化.互联网化,数字世界的找虫和杀虫就变得越来越重 ...

  3. Wine——在Linux上运行Windows软件

    官网:https://www.winehq.org/ 参考: wikipedia 教你使用Wine在Linux上运行Windows软件 如何安装和使用Wine,以便在Linux上运行Windows应用 ...

  4. C语言中史上最愚蠢的Bug

    C语言中史上最愚蠢的Bug   本文来自“The most stupid C bug ever”,很有意思,分享给大家.我相信这样的bug,就算你是高手你也会犯的.你来看看作者犯的这个Bug吧.. 首 ...

  5. Linux历史上线程的3种实现模型

    一.概述                                                   这里以Linux为例.Linux历史上,最开始使用的线程是LinuxThreads,但Li ...

  6. UWP Windows历史上最漂亮的UWP框架出炉!!!

    UWP Windows历史上最漂亮的UWP框架出炉!!! 本框架基于微软的开源项目WTS开发,并在其基础上增加了FDS(流畅设计元素,高光.亚克力等).多语言系统.沉浸式体验(扩展内容到标题栏) 同时 ...

  7. Rokid开发者社区skill之【历史上的今天】之简介+玩法+设计+实现+心得

    Skill简介: 来源:好奇心.探索欲.趣味性: 资源:百度百科: 方式:实时获取,自动更新: 技能玩法: 想要进入历史上的今天这个skill,则对若琪说:若琪,打开历史上的今天. 想要了解某天的历史 ...

  8. Rokid开发者社区skill之【历史上的今天】

    技能名称:历史上的今天 入口词:打开历史上的今天 语音交互:(有些是先写上) { "intents": [ { "intent": "PAUSE_HI ...

  9. jQuery+Ajax获取百度百科历史上的今天

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. Openstack(十二)部署neuron(计算节点)

    在计算节点安装 12.1安装neuron(计算节点) # yum install openstack-neutron-linuxbridge ebtables ipset –y 12.2配置neutr ...

  2. PAT 1138 Postorder Traversal [比较]

    1138 Postorder Traversal (25 分) Suppose that all the keys in a binary tree are distinct positive int ...

  3. PAT 1075 PAT Judge[比较]

    1075 PAT Judge (25 分) The ranklist of PAT is generated from the status list, which shows the scores ...

  4. SecureCRT 会话空闲时超时退出处理

    参考文章:http://www.cnblogs.com/xuxm2007/archive/2011/04/21/2023611.html http://yunwei.blog.51cto.com/38 ...

  5. SQL Server System.Data.SqlClient.SqlException:已成功于服务器建立连接,但是在 登录前的握手期间发生错误

    一.错误描述 错误名称如上.整体错误如下: System.Data.EntityException 基础提供程序在Open上失败--> System.Data.SqlClient.SqlExce ...

  6. Python笔记 #08# NumPy: Statistic Basis

    数据分析的基本步骤: 了解你的数据(get to know your data), 做一些统计学处理(像僵尸一样盯着数字不会带给你任何灵感!) 实现可视化(get a better feeling f ...

  7. UVa 11582 巨大的斐波那契数!(幂取模)

    https://vjudge.net/problem/UVA-11582 题意: 输入两个非负整数a.b和正整数n,你的任务是计算f(a^b)除以n的余数.f[0]=0,f[1]=1,f[i+2]=f ...

  8. python 递归求阶乘

    #用递归函数求 n 阶乘的值 def factorial(i): : else: )# sum=n*(n-)!所以直接调用自身 n=int(input('请输入阶乘数:')) ): print('%d ...

  9. "CMAKE_CXX_COMPILER-NOTFOUND"

    CMake Error: your CXX compiler: "CMAKE_CXX_COMPILER-NOTFOUND" was not found. Please set CM ...

  10. python 随机选择字符串中的一个字符

    import random print(random.choice('abcdefghijklm'))