答案:It depends.

 

“你去屎吧!”

我猜一定会有人这么说。既然“

改天我也去发一篇“QUIZ: 园子一个用户发多少篇给个问题还看心情才给答案的文章才会让全园友崩溃,是什么原因”放首页来好了 ”这样的回复,上面那个想法也肯定必然的。好,那我先剧透一点:这个崩溃和里面的那一个字是什么有关,而且和你是什么职业也有关。

 

“靠,这怎么可能,你干脆说是人品问题好了!”好吧,如果你真这么想,那我也只好说,至于你信不信,我反正是信了。


其实我发这些个QUIZ的原因,是发现了一些有意思的问题,希望大家去实验一把。可是现在园子水平真的很不济,貌似愿意动手刨根究底的人并不多。这也是我在工作中发现的一种现象,很多人都“知其然不知其所以然”,并且心安理得。好吧,抱怨到此结束,下面来说说这个很奇妙的崩溃问题。

 

在我们的工作当中,发现了一个很奇怪的崩溃现象:(非常抱歉,没有任何截图,描述的也不是很清晰,因为这不是我的工作,也就没有第一手资料。)

1、某些人的机器永远会崩溃,无论是用什么浏览器都一样;而另一些人的机器则无论如何都复现不出来;

2、对于会崩溃的机器来说,则在某些个页面上打一开始就崩溃。尤其是IE7,会直接弹出一个红叉对话框,里面一串十六进制数字,显示类似Access denied之类的类似C++错误提示的东西。.NET不是应该托管安全的么,怎么会这样呢?

3、对于崩溃之前的那一瞬间,既没有看到占用内存大小有什么特别不正常,也没有看到CPU负荷有什么不正常。 


对于上面的这个疑惑,我们甚至做了个Dump,开始的时候以为是IE7里面的某个COM组件的错误,因为用WinDbg看出错时堆栈位于当IE窗口大小发生变化之后所经过的代码。可后来的发现证明完全不是这么一回事,因为有人做了一个实验,发现出现崩溃和同一个页面上有多少个SilverLight应用有关。前面这个条件是必要但非充分的,因为在同一台机器上,有的页面不崩溃,有的页面就会崩溃。差异就在于有前者只有1个SilverLight应用,而后者则同时加载并显示了4个应用。

 

可这解释不了为什么有的机器会崩溃,有的则不会。对于这个问题,我们做了不少的假设,比如说:系统内存大小,操作系统版本,浏览器版本,内存泄漏,没有正确的处理异常,各种线程安全问题,SilverLight核心版本不一致,开发版和普通用户版,等等,乃至中毒。随着前面那几个比较严肃的怀疑被一一排除,我们甚至笑谈到了人品的问题。因为开发的时候我们从来没有遇到过这个问题,只是在内部使用的时候,个别美工和设计师会出现这种尴尬的情况,而且没有一个开发人员能用他自己的开发环境复现这个问题。甚至还有人下载了Silverlight 5 Beta来试,发现临界值从4个变成了5个。这个结果让人哭笑不得:有变化了,但解释不了什么问题。

  

就在我们一筹莫展的时候,这位同事又做了一个简化实验:同时展示4个完全相同的SilverLight,里面就一个TextBlock,随便写了几个字。就这么简单的一个应用,如果一个页面显示4个,则会发生崩溃的机器仍然会发生崩溃。这时候我们就开始怀疑,这个问题真的跟我们写的代码,乃至.NET Framework中的托管部分没有任何关系了。进一步的实验发现,只要输入中文,或者使用了中文字体,就会崩溃。只要TextBlock中的是一个英文,并且没有指定字体,或者指定的字体是英文的,就不会崩溃。

 

现在问题指向就比较明显了:中文,或者中文字体就是元凶。到了这里,我们恍然大悟,怪不得会发生崩溃的机器,全都是美工和设计师的。这些美工和设计师因为工作需要,会安装各种你所见过或者从未见过的字体。这时候我们还非常惊讶的发现:

1、我们的Demo里面并没有使用任何特殊安装的字体;

2、即便我们把我们需要的字体打包到XAP里面,仍然不管用;

3、即便我们显示的是英文,但只要指定任意一种中文字体,也会崩溃;

4、对于安装了字体的用户,如果把注册表改了(也就是假装这些字体并未安装),崩溃的症状也就消失了。 

 

这时候我们发现,要解决这个问题,似乎就只能够告知用户,把某些有问题的字体给删掉,或者给他们一个禁用某类字体的脚本。但到底是哪一个,或者哪一些字体会出现问题呢?同事再次陷入了困境,因为实验表明:

1、某一些字体一定不会出问题,我们称为A组;

2、另一些字体则同时存在时,一定会出问题,我们成为B组;

3、将B组字体每三个分成1个小组,随便禁用任意1小组,就不会崩溃;

4、B组字体非常多,逐个实验很耗时间,但随即抽了几个发现,似乎禁用任意1个,也不会崩溃。

 

正当大家都在讨论,这时一个什么问题的时候。当当当当!我闪亮登场了,我说:那看起来不是某个字体有什么畸形的东西在里面导致了某种原因不明的错误,很可能是因为中文字体大小和英文字体大小的原因。尽管很奇怪,比如说崩溃之前内存也没有达到接近2G大小,不应该是OOM这种问题,而且我从来没有、将来也不会用到的字体,为啥要一股脑儿全部加载进来呢?但也不是不可能的事情,毕竟中文字体和英文字体确实有这个差异。在这个思路下面,我们做了这么两个实验:

 

实验一:在会发生崩溃的机器上面,把B组字体删除1个,使得同事显示4个应用不会发生崩溃,然后再加载第5个应用。结果毫不意外,崩溃了。

实验二:在之前我们认为不会崩溃的机器上面,加载N个应用,发现在大约加载到30个的时候,也发生崩溃了。注意,不是.NET报告的OOM异常,我们不可能靠自己写代码能解决此问题。


目前,我们的进展只到了这里,进一步的排查和问题的机掘可能会非常困难,因为已经远超托管范围内的世界了。这个问题最好是微软来解决,因为严格来说这时一个Bug。但是至少,这个QUIZ的答案有了:

 

如果包含中文,或者指定了任意一个中文字体,则一个页面包含1到30个左右的SilverLight应用就可能会导致莫名其妙的无法启动的崩溃。具体是多少还取决于你的职业,比如你是一个很无趣的程序员,这个数字可能是30甚至更大;但如果你是个天才美工,爱好装各种各样牛逼的中文字体,那么这个数字也许是1;而如果你在程序员和美工之间,这个数字就不定了,最常见的数字可能是3到5。哦,对了,还可能和SilverLight版本有关,比如说SL4的数字是4,那么SL5的数字就可能是5。

 

嗯,还有一个QUIZ,答案也敬请期待。 

 

作者: Sumtec 发表于 2011-08-19 15:54 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"