(图片来源于网络)
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. MVC和观察者模式

    用观察者模式实现MVC框架! http://wenku.baidu.com/view/eff8bab069dc5022aaea0007.html 写的不错! Observer和ConcreteObse ...

  2. rtcp多媒体控制协议应用

    rtcp package send/recv demo main.c #include <stdio.h> #include <rtp.h> #include <rtcp ...

  3. (转)关于EntityFramework中连接字符串的说明

    1. 基本格式 <connectionStrings> <add name="MyEntities" connectionString="metadat ...

  4. [LeetCode]160.Intersection of Two Linked Lists(2个链表的公共节点)

    Intersection of Two Linked Lists Write a program to find the node at which the intersection of two s ...

  5. 生成对抗网络(Generative Adversarial Network)阅读笔记

    笔记持续更新中,请大家耐心等待 首先需要大概了解什么是生成对抗网络,参考维基百科给出的定义(https://zh.wikipedia.org/wiki/生成对抗网络): 生成对抗网络(英语:Gener ...

  6. laravel 多图上传

    前台  name="photo[]" 后台获取  $request->file('photo');//获取多个图片循环

  7. JavaScript基础知识笔记

    做前端几年了,一直疏于整理归纳,所以这两天把基础看了一遍,加上使用经验,整理了基础知识中关键技术,旨在系统性的学习和备忘.如果发现错误,请留言提示,谢谢! 重要说明:本文只列举基础知识点,中级和高级内 ...

  8. 20145221 《Java程序设计》实验报告五:网络编程及安全

    20145221 <Java程序设计>实验报告五:网络编程及安全 实验要求 掌握Socket程序的编写 运行TCP代码包,结对进行,一人服务器,一人客户端 掌握密码技术的使用 利用加解密代 ...

  9. 【Android】使用BaseAdapter实现复杂的ListView【转】

    本文转载自:http://blog.csdn.net/jueblog/article/details/11857281 步骤 使用BaseAdapter实现复杂的ListView的步骤: 1. 数据你 ...

  10. ArrayList扩容

    jdk1.5 public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new Illega ...