一次由注释引发的“血案”

原文:一次由注释引发的“血案”

有几天没写博客了,今天有点时间,正好把前几天遇到的一件“诡异”的问题记录一下。

我是在前几天学习CSS时遇到这个问题的。当时看到某个网站有一个CSS效果不错,就想研究一下。由于代码很短,我不想将整个页面保存下来,所以我点击"查看源文件",找到这段代码并拷贝到测试页面中。

它的主要部分是这样的:

/*file设为透明,并覆盖整个触发面*/
a.files input {
     margin-left:-350px;
     font-size:30px;
     cursor:pointer;
     filter:alpha(opacity=0);
     opacity:0;
}

 
用FF查看效果,一切正常。但当我换到IE后,问题来了,没有出现预期的效果!

当然,大家看到这篇文章的标题可能就已经猜到大概原因是什么了。但当时于我却是一脸茫然(原网页在FF和IE下显示均正常)

于是我开始分析……

 

首先想到的是:

是不是我复制代码时遗漏了一些对FF来说不重要,但对IE却是必需的代码呢?

毕竟我只复制了一小段,而且CSS在各个浏览器中也确实有可能出现不兼容的情况。

为保险起见,我点击"查看源文件",并将其中的代码全部复制到测试页面中,运行,问题依旧。

这使我非常郁闷,为什么相同的代码,在别人那是正常的,在我这却有问题呢?

继续尝试。

这次我决定将他的整个网页保存下来。

于是我点击了IE的"另存为",将他的网页保存到本地,运行,效果出来了!

现在可以肯定是我前面的代码哪里错了。于是我再将保存在本地的网页打开,查看其中的代码,发现IE对上面的CSS代码进行了格式化:

A.files INPUT {
     FILTER: alpha(opacity=0); MARGIN-LEFT: -350px; FONT-SIZE: 30px; CURSOR: pointer; opacity: 0
}

 
大家就不用自己比对了,我直接说结果:这两段代码是完全一样的,除了大小写和属性定义的顺序之外。

我们知道CSS是不区分大小写的,而且通常来说,不相干的属性之间的顺序也是无关紧要的。但我还是抱着谨慎求证的态度决定亲自验证一下,我将之前的CSS用这个替换掉,然后用IE打开,然后……显示正常!

但谁能告诉我,这TM到底是为什么吗?

难道真的是大小写或者顺序的原因?不管你信不信,反正我是不信。

然后我决定再改回原来的代码再试一次。

a.files input {
     margin-left:-350px;
     font-size:30px;
     cursor:pointer;
     filter:alpha(opacity=0);
     opacity:0;
}

 
用IE打开——他TM又没问题了!相同的代码,改回去再改回来,结果居然是不一样的?我当时就在想我是不是被上帝当成愤怒的小鸟给玩儿了?要不然怎么会发生这么反人类反科学的事情!

忽然,我发现最后这段代码与原来的代码只有一点不同,那就是注释。

难道……是……注释?

不知道为什么,可能是灵感突发,我忽然想到了编码这个问题。我在IE中查看了我的测试页面的编码:GB2312;我又查看了原网页的编码:UTF-8

事实证明,果然是编码的问题。然而更多的问题来了:

1. 为什么编码会影响到效果?

2. 我查看了两个页面在FF下的编码,情况和IE是一样的(一个是UTF-8另一个是GB2312),为什么FF都可以正常显示呢?

3. 我后来是将整个页面通过"查看源文件"的方式复制下来的,为什么会和原网页的默认编码不一样呢?

经过一番思考和验证,我终于找到了第1和第3个问题的答案:

1.为什么编码会影响到效果

IE错误地解释了注释/*file设为透明,并覆盖整个触发面*/,因为这段字符是UTF-8编码的,最后的"面*/"三个字符的UTF-8编码为:0xE99DA2(面)、0x2A(*)、0x2F(/)

UTF-8将汉字用3个字节来编码,对英文字符是1个字节。GB2312对汉字是2字节,对英文字符和UTF-8一样是1字节

 
当IE试图用GB2312解释这段注释时,它错误地将0xA2(“面”字的最后一个字节)和0x2A(*)组合在一起,形成了GB2312字符:0xA22A,虽然最后的"/"正常解释,但"*"字符丢失导致了本该结束的注释没有结束。

我试着将注释内容换成别的中文字符,如"中中",发现在IE下也没有问题了,看来这是一个由不恰当的中文注释恰好导致的一个偶然的错误(很拗口吧,我故意的)

3. 为什么通过“查看源文件”扒下来的内容会和原网页的默认编码不一样

我仔细查看了使用“另存为”保存的页面源代码,其中有这么一句:

<META content="text/html; charset=utf-8" http-equiv=Content-Type>

 
原来人家设置了页面的默认编码为UTF-8的,但我的测试页面中却没有,所以IE使用了错误的编码来解析,导致出错。但诡异的是,我在"查看源文件"时无论是IE还是FF都没有这一句。这就是为什么我将“查看源文件”中的所有内容都复制过来也还是不行的原因。

至于第2点,我始终不太理解,为什么同样的情况IE不行但FF却是正常的?个人猜测是两个浏览器在实现上的差异导致的。如果你知道具体原因,希望能够不吝赐教。

------------------------------------

下面是总结时间:

1. 浏览器的"查看源文件"和真正的源文件是有差别的

2. 注释有时也会对程序的运行产生影响

在《Java解惑》一书中也提到过因为注释而产生问题的例子。书中的谜题15"令人晕头转向的Hello"和谜题16"行打印程序"两节,作者列举了两个因为注释而导致问题的例子:

谜题15的例子:

    /**
     * Generated by the IBM IDL-to-Java compiler, version 1.0
     * from F:\TestRoot\apps\a1\units\include\PolicyHome.idl
     * Wednesday, June 17, 1998 6:44:40 o’clock AM GMT+00:00
     */

如果你没看过Java解惑这本书,估计很难一眼看出问题在哪,只是一段普通的注释嘛。

问题出在注释中的"\units"这里,"\u"在Java中用来对Unicode字符进行转义,后面必需紧跟着4位十六进制数字,即字符的Unicode编码。但这里,"\units"显然违反了此约定。

谜题16的例子:

    // Note: \u000A is Unicode representation of linefeed (LF)

这个例子的问题与我遇到的这个问题就更相似了。"\u000A"是一个Unicode换行符,因此在编译时,这行注释将被编译器理解为:

    // Note:

     is Unicode representation of linefeed (LF)

显然,这也是无法通过编译的。

 

3. 最后,一些看似可有可无的细节也有可能会导致莫名其妙的问题。因此在平时写程序时要注意总结和遵守规范。不要嫌这些规范死板和繁琐,它们都是前人根据多年的经验总结下来的,通常能够让你远离错误。

 

好了,今天就到此为止吧,一个看似简单的小问题,随便记录一下。

 

 

 

 

时间: 2024-09-30 23:02:33

一次由注释引发的“血案”的相关文章

一次马失前蹄的SQL优化:递归查询引发的血案

作者介绍 黄浩:从业十年,始终专注于SQL.十年一剑,十年磨砺.3年通信行业,写就近3万条SQL:5年制造行业,遨游在ETL的浪潮:2年性能优化,厚积薄发自成一家.   在上个案例分享时,有读者表示"很想知道,作者失败的时候是怎么办?",并且看热闹不嫌事大,要求"来一篇文章呗".好吧,正所谓,常在河边走,哪有不湿鞋.本人在SQL优化领域摸爬滚打多年,"接客"无数,难免会遇到些难以伺候的"官人",本文就跟大家分享一次不成功的优化

一个由正则表达式引发的血案

今天为大家送上一篇很有意思的小文章,具有提神醒脑之功效.作者是来自阿里巴巴LAZADA产品技术部的申徒童鞋. 1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求: 1. 英文字母大小写 2. 数字 3. 越南文 4. 一些特殊字符,如"&","-","_"等 看到这个要求的时候,自然而然地想到了正则表达式.于是就有了下面的表达式(写的比较龊): ^([A-Za-z0-9._(

[WCF]缺少一行代码引发的血案

这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性.具体来说,这是一个关于如何自动为服务接口(契约)的每个操作添加FaultContract与WCF服务元数据发布的问题.接下来通过一个简单的实例来说明这个因为少写了一行代码引发的血案. 一.手工添加FaultContract WCF采用基于消息的通信方式,Endpoint的ABC三要素之一的契约(Contract)的本质就是定义消息的结构.契约不

一个等号引发的血案(谈Nginx正确的404配置)_nginx

这是一个血淋淋的教训,这么说一点也不过分.因为最近发生了一个重大问题,网站流量大幅下跌,跌了近80%了.由于事件发生之前做过一些工作,加了大量友链,而且外站权重都相当高,在那天还发生了一次挂马事件,当然也即时解决了.还做了其它一些关键字内.外链优化等等.这样使得查找问题的原因就变的难上加难.偶然的原因发现,百度收录的链接开始出现错误,由于网站URL方式采用的目录式结构,最后一个字符都是/,然而百度收录的页面却无缘无故把这个线去掉了,而这种访问方式,我并没有做兼容.当时也查看了网站页面上的重写结果

一场越狱引发的血案:越狱开发者社区的崩裂,以及“中国队友”不按套路出牌的玩法

[更新]今天下午"快用苹果助手"召开发布会,正式对外发布越狱工具"太极 7",并公开承认"太极助手"为快用旗下产品.快用 CEO 谢雷表示,由于 bug 原因快用将暂时停止和 evad3rs 团队的合作,并且太极团队将单独发布越狱工具......这是一场越狱引发的"血案"......著名的越狱团队evad3rs昨晚在毫无任何征兆的情况之下,放出 iOS 7 的越狱工具 evasi0n7.和之前越狱不同的是,evasi0n7 越

Bitmap.recycle引发的血案

从Bitmap.recycle说起 在Android中,Bitmap的存储分为两部分,一部分是Bitmap的数据,一部分是Bitmap的引用. 在Android2.3时代,Bitmap的引用是放在堆中的,而Bitmap的数据部分是放在栈中的,需要用户调用recycle方法手动进行内存回收,而在Android2.3之后,整个Bitmap,包括数据和引用,都放在了堆中,这样,整个Bitmap的回收就全部交给GC了,这个recycle方法就再也不需要使用了. 然而-- 现在的SDK中对recycle方

在PHP应用程序开发中不正当使用mail()函数引发的血案

一.前言 在我们挖掘PHP应用程序漏洞的过程中,我们向著名的Webmail服务提供商Roundcube提交了一个远程命令执行漏洞(CVE-2016-9920).该漏洞允许攻击者通过利用Roundcube接口发送一个精心构造的电子邮件从而在目标系统上执行任意命令.在我们向厂商提交漏洞,发布了相关的漏洞分析文章后,由于PHP内联函数mail()导致的类似安全问题在其他的PHP应用程序中陆续曝出.在这篇文章中,我们将分析一下这些漏洞的共同点,那些安全补丁仍然存在问题,以及如何安全的使用mail()函数

一个冒号引发的“血案”

备课中. 从下载的PPT中复制出例题,调试一下,结果: 何其多的错误,红红的. 不正在声明Base2吗?怎么会"error: 'Base2' has not been declared" 斗争! -- 小样,就一个符号的问题,犯得着兴师动众,给出那么多提示?!红红的一片,血案发生? 编译器就是这么好,严格把关,各种提示. 亲爱的读者,看出来了,会心一笑吧. 编程就这样,给人带来愉悦.

一个脚本引发的血案

我们本身是一家互联网金融公司,公司的主流业务就是p2p,因为各种原因吧,15年底启动建设众筹平台.考虑到前期开发过程中的一些弊端和架构经验,本次架构引用了dubbo做soa服务的治理,web容器nginx+tomcat,后端语言采用java,框架选择spring+mybaits,前端模板引擎使用的是btl,app采用原生+h5的模式.这个架构可以参考我之前写的文章从零到百亿互联网金融架构发展史中的第三代系统架构,之前的文章主要介绍了架构的变迁,本篇文章主要介绍在第三代平台中遇到的问题以及解决方法