从string.strip()引起的一个bug说起


前两天修正了一个string.strip()函数引起的bug,bug很普通,但是查bug的过程值得思考。


事情是这样的,那天我正在欢快的写着程序,突然一个策划在popo上叫我了。

“hi,麻烦帮忙查个问题。现在给玩家的一个弹幕提示中,某某玦被显示成了‘某某?’”

我一看,这个”玦“我都不知道怎么读,看来是个生僻字,可能是编码出了问题吧:
“看上去好像是生僻字的编码导致乱码了,你找个客户端程序GG问问?”

“好的”

……
……
很久无事
……
……
“找客总(某资深客户端程序)问过了,他说客户端就是直接显示服务端传过来的数据的,没做修改”

这,锅又回到我头上了,不接也得接了:
“好,我查一下先”


这时,我还是有点不信这是服务端的黑锅,所以打开内服测试了一下,确实可以稳定重现。又通过几个GM指令让这个名称分别出现在包裹、系统频道等位置,发现只有当“玦”字出现在弹幕提示中时,会显示成问号。

那么这时基本可以确定,不是客户端字符编码的问题了。(的确不应该有问题,这个字虽然生僻,但也是策划们喜欢用的道具名称之一,有问题应该早就发现了)。

接着,我找到了相关代码片段,发现发送给客户端的道具名称是直接从数据表中读出来的,按理说不应该有错。这不就陷入死胡同了么,难道是策划填表填错了?也不可能,毕竟“玦”出现在其他地方的时候都是显示正常的。


再仔细看一遍代码。

发现问题了,刚才找到的代码片段,是一个外层封装函数。直接向客户端发送数据的函数,还在更里一层。

就是在这更里一层,做了一些对信息的处理:

1
msg.strip('#hshow_clan_fort_info#h')

可以看到,这里的本意是,信息中如果有#h #h包裹的字符串,是不需要显示的,所以需要去除掉。但是strip的用法却不是这样的:

strip(s, chars=None)
strip(s [,chars]) -> string
Return a copy of the string s with leading and trailing whitespace removed.
If chars is given and not None, remove characters in chars instead.
If chars is unicode, S will be converted to unicode before stripping.

而”玦“字的编码是’\xabi’,这样strip函数就导致了”玦“字变成了’\xab’,这样客户端显示成”?”也不足为奇了。

这里,用

1
msg.replace('#hshow_clan_fort_info#h', '')

即可解决这个bug。


到这里bug修好了。一个很简单的bug,正常应该十分钟就能搞定,但是这次却消耗了一个多小时。我觉得主要是没有注意以下几点:

  • 第一反应一般是不准的。对于这个“玦”字,虽然不常见,但是也不能归为生僻字,尤其在游戏中,更是常用。如果当时能多思考一下下,就能省去让客户端程序帮忙的时间。

  • 拿到现象,先看代码,再找逻辑。在上面的处理中,我确定问题在服务端之后,并没有直接看代码,而是先去内服重现了一遍情况。对于这种简单的问题,并不需要保留bug现场查看数据,所以其实应该直接去看代码逻辑,这样也能节省不少时间。程序员的工作是面向代码的,而重现bug的工作就交给QA大大们好了,术业有专攻嘛。

  • 不要推卸责任,要用于承担,及时反馈。程序员不知不觉就会推卸责任,虽然大多数时候是无意的。比如,经常说“这个东西在我这里是好的啊”(是你的机器有问题)“这个东西昨天还是好的啊”(这段时间肯定有其他人改坏了)“这块逻辑我都没改过”(是其他人的问题),这种行为可能只是个条件反射,但是其实是挺影响自己的“可合作性”的。遇到PM/QA反馈来的问题,不如先应下来(“我先查一下”),再及时的反馈检查的结果,这样既省去了扯皮的时间,又给人留下一个敢于承担责任的靠谱印象,何乐不为。对于带团队的Leader来说,对于背锅更是要有舍我其谁的勇气,不然谁愿意死心塌地跟你混呢?

最后,与诸位共勉,做一个靠谱的程(bei)序(guo)员(xia)^_^


转载请注明出处: http://blog.guoyb.com/2016/08/06/something-about-strip/

欢迎关注我的微信公众号TechTalking,技术·生活·思考:
后端技术小黑屋

Comments