2017年6月22日星期四

防贼不编年史

Chapter One
很早的时候,赛博世界还只有病毒,没有贼。
那时候,有的病毒还可以和人类和睦相处,称之为“良性病毒”。
我有一个游戏,从别人那边复制过来的时候,就是带毒的。文件型病毒,文件体被加了密,还给搬到了隐藏扇区。不过游戏本身挺有意思,The Incridible Machine,第一代。于是我每次就把BIOS里的硬盘给Disable掉,然后再玩。慢虽然慢点,但只要记得玩过之后重启,就不会有什么问题。

Chapter Two
尽管兜里没什么钱,但Internet时代还是到来了。
网管差点把我从网吧赶了出去。因为他终于“逮到”我在用SuperRabbit。他已经连续好几天都把时间花在恢复系统设置上了。我想日后硬盘还原卡卖得这么好,其中应该有我一份功劳。
“机器狗”真不是我放的。

Chapter Three
CIH爆发了。
买了刷ROM机器的人都发了笔小财。
其他人:哇,没想到病毒也可以这么凶残!
我倒是没什么感觉,因为我那个时候还在用着一块80486。

Chapter Four
IDT-C6的发热好低,主频超到100MHz也不用风扇。
哇,有好多同学都安装了冰河哎!
咦,这位同学在玩美少女梦工场3呢。我只有2。
“同学你好,你的游戏可以也copy给我一份吗?”
“哎哎,不要关机!……”

Chapter Five
不知道从什么时候开始……
几乎所有的IT公司,都以在你的IE上装一个插件或工具栏为荣。
几乎所有的安装包,都会附带一两种“小东东”。
刚开始我还真没太放在心上,甚至对某些还持欢迎态度。然后,我的机器越来越慢了。
做毕业设计时,我接触到了ActiveX。

Chapter Six
工作了。从K6-2一下子跳到Pentium 4的感觉真好。
“见鬼,这浏览器上什么时候多了这么些鬼东西?上网助手?中文实名?卸掉!就是它搞得我们的OCX不能用了。”
“你要记得安装Windows 2000 SP4补丁,不然我们的程序用不了。”
对了,有个新软件叫VMware,真好玩!

Chapter Seven
我开始小心翼翼地上网浏览,对于弹出的OCX安装提示统统点“否”,后面视情况而定。因为我知道一旦安装了之后别人能做些什么事情。然而,有些人我是注定帮不了他们:
“你的IE上装这么多工具栏干什么?”——“不然我怎么上网?”
Google的网址是三达不溜点……”——“别说了我记不住。”
愿上帝保佑他们,A门。

Chapter Eight
换工作了,当小头头了,总算有双核电脑用了。VMware可以有自己单独的CPU了。
真不敢相信,以前在一台768MB的P4笔记本上跑了一个Oracle8i+两个Lotus Domino R5+一个Resin+Word+若干IE,去招标现场做演示的时候,机器到底是怎么撑下来的。
借着新工作接触到了IceSword。妖魔鬼怪你们都现出原形罢!
测试人员:不好了,机房又爆发“震荡波”了。

Chapter Nine
我开始仔仔细细地打补丁,开启Windows Update,总是保持自动更新。
而很多同事都是直接关掉了事:“工作到一半老是跳出来叫我更新,太烦!”
愿上帝保佑他们,A门。

Chapter Ten
我发现同事们总算愿意给机器打补丁了。
同事:这个东西叫360,打补丁蛮快的。
我:我也来试试。咦,这个KB360018怎么这么奇怪?

Chapter Eleven
不知道从什么时候开始,软件安装开始必须得小心了。
因为一不小心你就会安装上好几个不请自来的软件,电脑上会变成软件博物馆。送来给我“修一下”的电脑无一不是如此。连我自己有时候不小心也会中招。
有人建议我把家里电脑换成Linux,不过我觉得对父母吩咐到位了,一般还是没事。毕竟我有TeamViewer

Chapter Twelve
不知道从什么时候开始,国产软件慢慢地不能用了。
其实不是不能用,是不敢用了。因为开始流行一种东西叫做“全家桶”。腾讯、百度、迅雷、阿里、360、金山……。所有的这些曾经为我服务过的软件,仿佛都得了癌症。你不知道他们在背后干些什么,但是你的电脑的确越来越慢,行为越来越不正常了,而且你的hosts总是失效得很快。于是干脆就不用了。
不用了,然后也并没有什么事情发生。并没有像有的人以为的那样会社会大乱,民不聊生。人民照样活得很好。

Chapter Thirteen
一夜之间,我的密码就不再是“我”的密码了。
许多年前,我自己写的同学录,为了避免被SQL injection,就把服务端存储的密码改成了MD5 Hash。
后来,知道了世界上有种东西叫做“彩虹表”,于是我学会了salt
再后来,我看到了王小云教授的论文,于是我Hash算法至少会是SHA256。
然而,这么多年过去了,这帮狗日的居然还在服务器上存明文密码。谁要硬说这里面没有阴谋,我只能说你的心挺大。

Chapter Fourteen
没想到,我的QQ也被盗了!
我已经很多年没用过QQ了。但是因为我太太的手机上有游戏用我的QQ账号登录着,所以我觉得企鹅还不敢回收我的账号。
突然间它就变了一个名字,列表里的好友也变成了一堆海南人。我还能再登进去,密码并没有被改。所以我一直到现在也没想通是怎么回事。
我把个人状态改成了“明文密码好”,然后就把这个QQ号扔那里了,就像它从未存在过。

Chapter Fifteen
那个周末,当我还在外地顶着紫外线用流量上网的时候,全世界有许多人已经了。
贼要的是Bitcoin
当第二天IT问我笔记本装没装补丁的时候,我微笑着告诉他“Linux”。
不过我马上又想起来Heartbleed的事情我还没处理,于是我又有点笑不出来了。
我也想要别人的Bitcoin。

2017年6月13日星期二

银联钱包你真垃圾,我一点都不欢迎你

5月30日一下飞机,我就在虹桥T2的廊桥里面看到了银联云闪付62折的大幅营销海报。“去看看有没有便宜可占”,当时我这样对太太说。然后我们就各忙各的,这事几乎给忘了。

昨天太太跟我说,超市里面银联云闪付满79减30,所以她在自己的iPhone6+上装了个银联钱包。我想起了在机场看到的东西,就也去AppStore上搜了一下。有两个东西,一个叫“银联钱包”,一个叫“云闪付”,都是“中国银联”出品的,评分还真是一样低。我有点纳闷,好吧两个都下了,反正AppStore上至少没木马。

安装好之后把玩了一会儿,“云闪付”一来就叫我登录,而“银联钱包”至少让我看到里面有些什么功能了,里面也有“云闪付”的功能,那么好,“云闪付”你滚蛋吧。

其实我知道Apple Pay本来就是所谓的“银联云闪付”,我只是想知道银联这次在玩什么花样。结合新闻我有点弄明白了:大概闪付需要芯片,很多地方只肯买扫描枪,所以银联这次也搞了个跟支付宝有点像的扫二维码支付。这就必须要App支持,光靠Apple Pay还不行。

好吧,我觉得至少比起阿里粑粑这种流氓公司而言,银联我还可以尝试一下。于是我准备注册了……

我真的没想把本文写成吐槽文。不过正式开始用的第一眼我就被雷到了。拜托!中国银联!这是iOS,是哪个老师教你“自己开发密码键盘会更安全”的?你说出来我们来轮他。

先得注册。我在界面上看到了可以用“手机号”、“邮箱”或“用户名”来注册。我并不是一个暴露狂,所以我准备以用户名来注册。点开App上的注册,发现只能用手机号注册。我不死心,换到PC上在Web下注册。一开始Web页面看起来也只能用手机号注册,不过当我F12之后,就发现还有一个DIV被display:none了。
呵呵,我心想:“就这也能难住老子?”
看来还是绕不开。

然后还有这个令我一看到就恶心得头皮发麻的“请点此安装”。
我用的是Chrome,要我换用Edge甚至是IE我都可以接受。不过要我安装OCX那就太过分了,。有的Web页面如果用手机浏览器打开,就不会提示安装控件了。我抱着姑且试一试的态度,用手机试了一下:
Chrome是这样,Safari也是这样。
好吧,反正就是必须得要手机号对吧。那我还是回手机App上去注册吧。

在App上输入手机号码,通过短信发了验证码给我,验证通过了,接下来让我输入密码。这明显的大爷作风嘛。我很想问银联你是不是并不在乎有没有用户来注册?老子是国企多一个少一个无所谓?你们知道像美团之类的App在这一步是怎么做的吗?
我又要吐槽了。最低6位虽然太少,但我可以理解。最多不能超过16位是个什么意思?你们如果后台数据库里面保存的真的是密码的Hash值而不是原文,你管我密码最大有多长?你们知道Twitter允许的密码最大有多长吗?你们可以自己去试一下。
明文密码!我一直不厌其烦地在Twitter和Google+上强调这个事情:只要没有特别的理由就限制密码的最大长度,那后台保存明文密码的可能性就一下子变得高了起来。不要跟我讲什么16位现在还足够安全。关键是撞库!撞库!撞库!
我一直是坚持“为每个服务使用独立随机密码”这个原则的。我宁愿忘掉密码,宁愿冒本地密码本被人搞走的风险,我也不会把心放在Server管理人员身上。原因很简单:做过这行你就知道了。
所以,我开启了密码生成器,去掉“符号”的勾,选择了长度为“16”,然后得到了一串随机密码。知道我前面为什么吐槽自己做的密码键盘吗?你既然决定了自己做密码输入控件,就很可能不会支持复制粘贴。
在我比较辛苦地输入完密码之后,出来一个这个。
估计我以前在什么时候注册过银联的账号吧。有句妈卖批我不知当讲不当讲?!我输入手机号码的时候你不告诉我,我输入验证码的时候你不告诉我,我输入密码的时候你不告诉我,等我把这些都搞完了你就告诉我这个?!
抱着一丝希望,我点下了“是我的,立即登录”按钮,App跳回到了最开始的登录界面,输入我刚才生成的随机密码(是的我又辛苦了一遍),说我密码错。这次我真的骂人了。
好吧,看来我只能选择“忘记密码”了。
在又通过短信验证了一遍手机号之后,给我看的是这个界面。
我曾经在Blog中讲过,“密保问题”并不是一个好的设计。不幸的是,银联这里选的是所有密保问题中最糟糕的那几种之一。如果真的用家人生日做密保问题的答案,安全性极其脆弱,有等于无。如果用别的答案,又极容易忘记。
偏偏这里不回答还不行,又没有提供“忘记答案”的选项,实际上是把这条路给堵死了。然而手机短信验证的安全级别明显比密保问题要高。取信低安全等级的验证结果而忽视高安全等级的验证结果,最后只能请求人工服务,这是极差的用户体验,也是极蠢的产品设计。

如果我记不起这个以前注册的账号的密码,我可能就只能打电话给银联了,而且可能这帮官腔佬最后还不肯替我解决。不过很幸运,我用一个旧密码最后成功登录了进去——看来我注册的时代还不太“古老”。
然后我又被雷到了。登录成功之后,App给我看了这个:
是的,没有“跳过”或者“稍后设置”的选择,这一步是必须的。
设置手势密码之后才可以设置TouchID。好在根据太太的经验,登录进去了之后是可以把手势密码功能给关掉。不过问题又来了,要进入“安全设置”你必须要:
到这一步,我彻底放弃了。
极其差劲的技术运用,极其糟糕的用户体验。难怪AppStore上绝大多数评价都只给了一星,而近期的五星好评全像是刷出来的。我估计如果AppStore不是规定最低是一星,很多人连这一颗星都不想给。
说实话,我不相信这种程度的技术能够保障我的资金和信息安全,给我天天打62折我也不敢用。算了。卸载。再见!


2017年5月31日星期三

淘宝天猫都碰不得啊

前言
六一儿童节快到了,给儿子买点什么礼物好呢?虽然前不久刚买了一架UH-60和一把Glock17,但我还是想买点对儿童稍微有点教育意义的东西。思来想去,觉得地球仪不错。正好暑假也准备带家人出国去转转。若是连自己去了哪里却一点概念都没有,那岂不是很遗憾?

平时工作也算得上忙,所以我就偷懒打算在网上购物。碰巧近来网购的体验还不错,正所谓好了伤疤忘了痛,我又开始在淘宝上逛了。

其实以前我是很吃过几次亏的,所以也曾经痛下决心告诉自己大部分东西都不能在淘宝上买了。但前不久那次买玩具的感受实在是不错:我擦!居然有金属的Dragunov?这次一翻地球仪,我更是震惊了:我擦!居然还有磁悬浮的?!

所以说啊,人必须时刻保持冷静,才能抵挡诱惑。头脑发热之下,我真的就下单买了个所谓的“磁悬浮地球仪”。带着残存的一丝丝理智,我选了一家天猫店下单。我觉得吧,C2C的淘宝不靠谱,B2C的天猫大概好一点,至少出了问题比较好解决。事后证明,我这想法也对也不对。

糟糕
等待收货的过程还是蛮引人遐想的。然而收到货一拆包装,首先心里凉了一半:包装倒没有什么特别的问题,不过产品外包装上连半个汉字都没见到,没有品名,没有厂家名称,没有商标,连个LOGO都没有。好在我是懂英文,加上有个图片,还能看出来没发错货。
打开盒子,里面除了地球仪和一些填充物,就只有一张非常简单的“说明书”。合格证、保修卡,什么都没有。这它妈的不就是传说中的“三无产品”吗?
好吧,网购的东西,要求别那么高,毕竟地球仪才是主要的。我对它有着不小的期待,因此心里倒也没怎么在意那些“细枝末节”的事情。看了看说明书,通上电源,开始折腾。折腾着折腾着,汗就下来了。
要完成所谓的“悬浮”,好困难啊!

虽然买之前看过一些评论,算是心里有所准备,但还是没想到这么麻烦。送的那个什么“悬浮棒”根本就不好使。还是有个评论里面说用中性笔的办法比较管用。好不容易能够比较顺利地“悬浮”上了,然而只要有一点点扰动,平衡立马就被打破,通常的结局就是地球仪被“铛”的一声吸到顶上。而且就算是很小心地退开,一般也坚持不了几分钟。我发现这大概跟加工精度有关系,因为顶上的磁体是斜的,而我无法去校正。
并且,产品说明里面提到的自动旋转,似乎也无法达到。球体也就是左右来回转,每次角度也就是几十度。我定睛看着它,发现角度在越来越大,正当我满心希望它最终能转一个整圈的时候。“铛”,它又被吸到顶上去了。

这它妈让人怎么用?我不可能每天都花一两个小时的时间在折腾这东西上。睡觉时还不能开着,不然保管神经衰弱。要是只能摆着或吸到顶上,那几十块的普通地球仪岂不是更好?我干嘛买个这么贵的银样蜡枪头?
不行,退货!

退货
在淘宝上买东西,顺利的话一切都好。然而一旦买到糟糕的玩意儿需要退货,那麻烦就来了。我以前的糟糕的购物经历无一不源自于此,这次当然也不例外。当我以“质量问题”为原因要求退货时,卖家拒绝了。我对此也并不意外——反正最糟糕也就是哪样,总不可能直接投降吧。

卖家拒绝的理由看起来很好笑——产品有正规工厂专利进货发票。这话好眼熟啊!对了,我以前在某个论坛上看卖家们交流心得时提到过,如果被投诉三无产品,就这样应对,只要你拿得出发票来,淘宝小二可不管它是不是真的……。呵呵,这样的发票当然可以买。有些买的发票连税务局那边都能过,何况淘宝。淘宝的处理方式很简单,C说你卖的是假货,你B有发票吗?噢,有,那C你去证明B卖的是假货……
我去你妈的。

这个时候我看到了一个“极速维权”的按钮。我点了一下,叫我提交证明。
我能怎么证明呢?我只能把上面那两张图片传了上去。产品不能正常使用,我能怎么证明?上传一段小电影吗?搞笑。我都能想得到接下来的过程,无非就是叫C去找质监局,出具鉴定证明。普通消费者常常到了这一环节就望而却步了。较真的可能会去工商局投诉,然而一般也是了无下文。

要说起来,这个环节是很给“天猫”加分的地方。我刚上传了照片不久,天猫说因为我是“信誉良好”的顾客,所以给我先行赔付了。的确也是马上就是进入到退货发物流的环节了。听明白了吧——东西真不真我不表态,但是我相信你!
很多时候,事情就这么摆平了。你要认真按“假一罚N”地去索赔,那可就没这么容易了。职业打假人毕竟是少数。这一招就叫做“分化瓦解”、“团结大多数,孤立一小撮”。

给东西重新装箱的时候,我又留意了一下这东西的做工,才发现其实粗糙得很,根本不值169元这个价钱。所谓专利号,搜了一下是宁波一家公司的,跟淘宝商家八竿子打不着。如果光看成本,20元都不一定有。尽管到淘宝上买东西没一个不是想贪便宜,但你一定要相信,卖家不会让你真正占到便宜的。

运费
我记得,我上次在Blog上吐槽淘宝的事情,最后问题也是出在退货的运费上。这次又是“也不例外”。可见,如果那里的确有一个坑,你再走几次也还是会掉进去的。

天猫很“贴心”地提供了“上门取件”服务,还可以约时间。说实话,当时我真的有点小“感动”,几乎就要拍手叫好了。

取件的人来的时候,我在上班,是我太太处理的。取完件我立马就收到了退款。然而收快递的人跟我太太说,运费本来是7元,但是要收11元,因为“你的东西超宽了”。
好吧。我心想,反正质量问题的退货运费是应该由卖家承担的。所以我也就没有坚持太多。收快递的人(我不想用“快递员”一词称呼他,因为我对他有意见,我觉得他不配)叫我支付宝直接付掉,我打开手机的淘宝App,的确有付款按钮。我点开看,7元。

怎么回事?也许是对方还没提交新的价格。我就又做了一些手头的工作。一个小时以后再去看,还是7元。
7元就7元,我心想,也许系统不觉得我的东西“超宽”。付完款没多久,太太说快递员打电话来,叫补4元运费,给了支付宝地址。
妈的,现在想起来补运费了?

结束
问个问题:太监下面有什么?
太监下面没有了!
居然什么都没有了?

质量问题导致的退货,运费不是由卖家承担吗?如何承担?要我“垫付”已经是足够糟糕的体验了,然而现在是要我去找卖家聊IM来“讨”吗?
我最憎恨的就是这种“干点什么都要IM”的事情。而前几次还算“愉快”的购物体验,也正因为我“不用到IM上做任何事情”。

好吧,既然天猫觉得这个事情“到此为止”了,那我对你淘宝/天猫也就“到此为止”吧!
其实总结下来,写了这么多,无非是想让自己记清楚这些个教训。有钱留着去国外花,别它妈犯贱去交智商税。

2017年5月26日星期五

刘胡兰终究是要滚蛋的

最近,刘胡兰这位“小作死”又弄出点动静来。起因是2014年有个家长写了篇文章在说让刘胡兰离我的子女远一点。这篇文章这几天被翻出来,制造了一些话题,然后“共青团”予以了反击,弄出了一些浪花。

在正常人看来,家长的理由很充分,很正当。我想大多数爸妈也不会想让自己的小孩去当“刘胡兰”。何况,就算人总有一死,死成这个“刘胡兰”这样也并不是很光彩,甚至还有一点“脑残”。这些都是常识,不具备的人看到这里就没必要往下再看下去了,不然你血压又要升高了。

说起“刘胡兰”,我回想起以前学校的一桩旧事。某天开家长会,母亲回来说有同学被老师批评了。原因是老师听到该生在拿某篇课文打趣,说:“‘革命烈士’的‘鲜血’流在地上都结了冰,这太浪费了,干嘛不拿来做成‘血旺’”。

现在回想一下,大概就是这篇课文,因为翻了翻维基百科我记起了刘胡兰还有六个同伙,也像CIA线人一样被当场处决了,好像就是这种场景。

当时那位同学的家长作何反应,我不知道。想来脸上不太会有光,倒不是因为刘胡兰,而是因为“差生”的家长本来就在家长会上抬不起头。在家长会上会被公开批评的,自然是“差生”,老师批评起来才比较肆无忌惮。我这种“优等生”她还指望着去给班级、学校拿各种奖,各种“荣誉”,所以即便是在游戏摊看别人玩游戏看到天黑被当场抓住,也是“内部处理”了事。不过我相信这位“差生”一定比很多“优等生”要更有人味儿。这大概是我所知道的最早的对于洗脑式教育的公开反抗行为。

时代的确在变,当年抬不起头只能回家训孩子的家长,放到今天,也许就是微博或微信上的一篇《请刘胡兰离我的孩子远点》。刘胡兰终究是要滚蛋的。不管猪民仍旧有多愚昧,共产党啊!你知道吗?真的是回不去了。

江水东流,一去就不回头。发出去的钞票,哪那么容易回收。你的确是可以多拦几辆电瓶车来投入更多的资源,搞出一些逆流。然而,你终究是要滚蛋的。爱查顿在上!连人类都终究是要滚蛋的。借用Cromartie的一句酷酷的台词作结:

We'll see.

2017年5月25日星期四

将C++11新特性用于代码优化

关于C++11的科普,在这里就不详细进行了,可以参考维基百科页面。即使是中文页面,我认为写得足够详细和系统了。

总之,C++11对原始的C/C++作出了在我看来是不算小的改动。有一些概念,放在以前的时代是绝对真理,在C++11推出之后,可能需要重新了解一下了。VS2013对C++11的支持并不算“完美”,不过大部分“有用”的特性还是到位了。这里就以它为例,来谈谈如何把C++11的新特性应用到你的软件开发工作中来提升性能和开发效率。

本文提到的C++11的这些新特性,我大致把它们分为两类:一类是可以直接提升代码的性能表现的,我列在“性能优化”部分;另一类虽然不能直接提升代码的性能,但可以提升开发效率,便于更快地开发出可维护性更好的代码,我列在“非性能优化部分”。

另外,受作者水平所限,本文并不是对C++11在这些方面的完整的参考内容,仅仅作为一个引导来阅读吧。


性能优化部分

右值引用和move语义
C++11引入了右值引用,支持了move语义。在我看来,这个变化的意义可能是C++11里面最大的一个。右值引用和move语义是什么,这里不展开。通俗一点地讲,这个特性使得程序员可以在必要的时候自行决定到底是深拷贝还是浅拷贝。对于大量的数据“搬运”操作,可以节省下不少时间。对于性能优化来说,意义重大。

其实就算没有右值引用,在C++11之前的时代也可以做类似的优化。C++程序员只要对于自己的资源管理类显式地提供深/浅拷贝版本的函数即可。不过这样一来代码工作量会比较大,程序会变得比较复杂,并且始终不是一个规范。现在这一切都不是问题了。

对于STL自己的类/容器,VS2013已经做了足够的优化。例如,你可以通过:
string strA = std::move(strB);
来把strB的字符串动态内存部分直接给到strA,速度比简单的赋值要快不少。当然,strB就不再具有有意义的值了(这里例子中会变成空字符串)。当你push_back或insert一个string到容器里面的时候,如果string其实是一个临时变量,那么用move语义你也可以得到相当明显的性能提升。

如果例子里面string换成一个map<string, string>,那么提升会更明显。总之,内存的分配和释放,以及memcpy操作统统被避免了。所以,理论上需要传递的东西越多,你得到的性能提升就会越显著。

就地部署(emplace)
C++11对于常见的STL容器,都提供了一种能提升性能的数据置入方法,称之为“就地部署”。通过用就地部署取代原来的push_back或insert之类的操作,不再需要先构造再传递,而是由容器直接调用目标对象的构造函数来完成数据填充。

在某些情况下(T提供了对应的构造函数时),这样可以避免一次拷贝构造的开销。而最差的情况(T没有提供对应的构造函数),也最多不过就是与push_back和insert效果一模一样而已。所以我建议所有能用上就地部署的地方,都统统用上,无需太多考虑。

并且,就地部署与move语义相互并不冲突,而且是互有补充。move语义解决深拷贝慢的问题,就地部署试图减少哪怕是浅拷贝的执行次数。两者配合起来效果更加完美。

散列表
在C++11里,不再需要通过第三方库来引入散列表(或者叫哈希表)了。STL正式支持了四种散列表的实现,全部都冠以“unordered_”的前缀,以便与一些第三方实现相区别。

对于大多数用map/set实现的代码,只要简单替换容器就可以得到性能上的提升。map/set基于红黑树(自平衡二叉树),时间复杂度至少是log(N)。散列表版本的map/set提供常数级的时间复杂度,随着数据量的增大,无论是写入还是读取的性能都超过了红黑树版本的map/set。

我个人的测试结论是:同是set<string>,即使是小数据量,散列表版读取代价也只是红黑树版的约60%;小数据量下,红黑树版写入略快,但在容器内数据量达到“万”级别的时候,散列表的写入速度也开始超越红黑树版(Release版测试结论,Debug版在“百”级别即发生超越现象)。

所以我认为,只有在数据量很小,并且写入与读取的概率大致相当时,使用红黑树版map/set才在性能上可能有明显收益。其余情况,都建议采用散列表版本map/set。当然,如果T是自定义类,并且你不愿意为它写散列函数,那就算了。


非性能优化部分

完美转发
C++11中所谓“完美转发”的特性,其实是配合右值引用来使用的。如果为了支持右值引用,而不得不让自己的代码量变大一倍,那有些人可能就要望而却步了。完美转发其实是借用了模板技术,使得你可以只写一份代码,就可以兼顾(常量)左值引用与右值引用的情况。工作量更少,代码更简洁,出错的概率也就更低。

不过,采用模板技术的缺点就是:编译期展开。这一方面降低了编译器的效率,另一方面会导致头文件的包含关系变得不太容易整理。除此之外,还有一种我称之为“不完美转发”的替代解决方案,本质上是在性能上作出一定程度上还算可以接受牺牲,来换取代码简洁性,取得一个还算OK的平衡。我会另外写一篇Blog来介绍一下它。

类型推导
“类型推导”也就是所谓的auto类型。这个东西使用起来基本没有门槛。很多人可能最开始接触C++11就是通过它了。

这个的确是一个好东西,用来写STL的iterator类型再合适不过了。因为我们本来也不怎么关心iterator的具体类型。不过,仍然不建议滥用。如果到处都是auto,阅读你代码的人会经常性地需要回顾才能知道一个变量的类型,特别是在你没有用匈牙利命名法的时候更是如此。

所以,我的建议是:当你觉得一个变量的类型写起来很麻烦,而你其实并不关心它的时候,放心地用auto。并且,auto变量的作用域不要太大,if/for/while循环内的局部变量用它是最合适的。

基于范围的for循环
很多语言早就可以这样写了。而C++11现在也可以这样写了:
for (auto& stk : stocklist)
相比起:
for (auto pIter = stocklist.begin(); pIter != stocklist.end(); ++pIter)
孰优孰劣一目了然。何况后者通常还需要跟一句:
auto stk = (*pIter);
不过,如果是一个map,你可能经常要取pIter->first/second之类。或者你打算在循环里面对pIter做erase操作,那还是用传统方式比较好。

空指针
用nullptr取代NULL。我觉得最大的好处就是nullptr的颜色没有NULL扎眼。不过,由于NULL也表示0,有的时候也表示无效句柄。我觉得对于所有指针类型的NULL,置换成nullptr可能会对阅读代码有一定帮助。

角括号
C++11的编译器现在可以识别>>到底是两个模板类的嵌套,还是>>运算符。因此写代码的时候就不特意空上一格,写多层模板类嵌套的时候就更美观一点。

不过,多层模板类嵌套,本来就不可能“美观”到哪里去。起码我是不建议太多此类的代码实践的。

初始化列表
vector可用这样的方式来进行初始化:
vector<int> vecX = { 1, 2, 3, 4 };
的确是比以前省事了。也就是说,C-Style数组的存在意义又少了一层。

统一初始化
struct可以被这样初始化:
struct C
{
    int a;
    int b;
    int c;
};
C c{1, 2, 3};
class的public成员也可以。
在某些喜欢使用各种结构体的代码中,这个特性可以让你少写一大堆构造函数。

通用智能指针
std::shared_ptr<T>,强在可以指向任意对象,缺点也由此而生:由于引用计数保存在shared_ptr中,因此对智能指针的赋值操作是线程不安全的。这个问题,有一篇Blog论述,我觉得写得不错,就直接引用不细讲了。从原理和测试数据来看,我认为这篇Blog是靠谱的。

所以,虽然shared_ptr很强大,但使用场合需要注意:单线程随便用。多线程下,赋值过程要注意。单对单没啥问题,最好不要出现左值右值交叉的情况(一个线程在A=B,另一个线程在B=C)。若因业务需求无法避免的话,要考虑当作临界资源加锁保护。实在不行,就写一个专用智能指针,把引用计数放在T里面,就不会有问题了。

正则表达式
与散列表类似,不再需要第三方实现,现在C++11也直接支持正则表达式了。我以前要找一个Unicode支持得好的Regex库真的是苦水一堆,现在有了官方支持真的是太好了。

2017年5月23日星期二

招行网银在Win10下糟糕的支付体验

我这人不用QQ,不用微信,微博借王维林也成功销号。然而,支付宝因为早年上淘宝购过物,搞过那个什么实名认证,我评估后认为不用比用下去可能更不安全,所以账号勉强留了下来。不过我也给自己定下了两条规矩:

  1. 不绑定银行卡的快捷支付。
  2. 不在里面保留超过200元人民币的余额(含余额宝)。

这两条规矩,使得我的支付宝平时基本上当作零钱包来使用,正式的支付只用在PC+网银上。这样,即使失窃,损失也很有限。再说,花钱方便是方便什么?方便你败而已嘛。

因为我自己定的这些规矩违反某些方面的利益,所以经常给我形成一些耐性上的挑战。昨天我就又遇到了一次,来自招行网银+Win10。
没有足够的余额,又不开快捷支付的话,在支付宝上支付一笔淘宝订单就只能通过网银了。我以前一直用招行网银,虽然它对Chrome和x64很不友好,但我还是耐着性子开x86 IE来在这种“特殊场合”将就一下。反正也就是最后一步嘛,登Alipay集中支付一下就好。但昨天在Win10机器上我又发现了新的问题:

Edge不支持
Edge登录支付宝是挺顺利的,但招行网银的页面一打开,直接说这是“使用陈旧技术的页面”。要想跨Browser提交表单估计还是做不到的,所以最后还是只有在Win10下打开Internet Explorer。

无管理员权限登录会失败
IE下几经折腾,可以打开招行的网银专业版了。然而插入UKey之后一登录就跳出Dialog让我输Key的密码。在确认不是钓鱼软件的情况下,连输4次后,专业版登录界面弹出提示说整数签名有问题云云。
我估计这问题就是因为权限不到位,果然给了管理员权限后就能正常登录了。然而专业版登录界面是从IE页面上Call出来的,这就意味着我得给IE管理员权限才行。这它妈风险真高!

以前我一直觉得,金融行业在IT技术应用上普遍保守,在国内看来招行还算是做得不错的。现在看来它在技术上已经落伍了,并且相当不思进取:x64都普及多久了?IE份额离开绝对优势地位都多久了?Win10正式版都上市多久了?到现在还在用着ActiveX。招行里面搞技术的人这些年都不知道在干啥。曾经引以为傲的服务水平也许还没下滑,但也绝对并不突出了。我是不是该换一家主力银行了?

2017年5月22日星期一

VMware+Ubuntu声卡失效事件

在公司和在家里,都用VMware各自安装了一台Ubuntu 14.04 LTS来玩。在家里的一台用得没有什么问题。在公司的那一台,周末打算加班的时候装个网易云音乐来听歌的时候,发现没有声音,才注意到VMware上有一条报错提示:
使用的设备标识号已超出本地系统范围。 声音将中断。
公司电脑上没有接音箱,所以以前曾经禁用过宿主机的Windows Audio服务。我以为是这个原因,去看了一下,Windows Audio服务现在是启用中。把宿主机重启过,故障依旧。于是循例开始Google。

Google上搜到的中文内容,主要分为两派。一派说把pulseaudio卸载了就好了。我半信半疑地apt-get remove pulseaudio之后,嘿,还真的可以播放出声音了。不过更大的问题来了:系统设置丢了好多图标。回想起apt-get提醒我说要卸载掉的东西有一大堆,看来依赖于pulseaudio的东西不少。这条路应该不是什么正路。真是还好VMware有快照。

另一派说把宿主机上的立体声混音设备启用,故障就解决了。附和的人不少,看来有不少人都是这种办法解决的。具体页面有很多,随随便便就能搜到,我就不给出了。然而当我按照附带截图的操作指南去做的时候,问题又来了:我根本没有立体声混音设备。

这是怎么回事?我这人也不习惯卖关子。要说还是英文信息有用。英文页面上也有少数几个人抱怨遇到与我同样的问题(中文页面上我没有看到过)。最后还是VMware官方社区给出了有用的解答

要简单解释一下的话,其实就是这么一回事:我这个宿主机上的Win7当初装起来之后,偷懒没有安装Realtek官方的声卡驱动程序,而是直接Windows Update安装了微软给出的驱动。估计微软的这个驱动是个阉割版,缺一些东西,装了之后虽然使用起来没什么问题,但像我这次遇到的什么立体声混音设备,大概就是被阉割掉的内容之一。所以VMware找不到指定的设备,于是就没法让Ubuntu中的声音设备正常工作了。

总之,按照VMware官方解答的指引,我去Realtek官网上下载并安装了声卡驱动,现在VMware里面的Ubuntu可以欢快地播放音乐了。