前段时间,在给我们游戏服务器写lua的脚本的时候,发现了一个奇怪的现象,一段lua代码只要一执行就把服务器给搞挂了,仔细分析了一下,发现这段lua代码并没有执行什么特别的操作,甚至都没有跟我们服务器的C++层交互,仅仅只是使用lua自身的一些库函数,而且只对windows平台下的服务端会产生这个崩溃。初步认为是windows平台的原因。于是我在windows平台下编译了lua的源码,跟进去后发现原来是宕在了windows的CRT函数里,解释一下CRT是windows的C运行时库,如果有朋友不清楚,可以看看《程序员自我修养》这本书中关于运行时库的章节,正好网上给出的示例章节就是这有这一章,可以看这里:http://book.51cto.com/art/200904/120986.htm

接着说我的问题,宕在了一次调用lua内置的os库的date()函数,调用如下:

os.date("%C")

跟进lua源码后发现,源码里最后调用了C库的strftime函数:

wKioL1NGEwagdDUeAAIB-KSz6Rs123.jpg


打开,因为我们的服务端编的都是debug版本,vs编debug版默认使用的多线程的那个debug版本的库:

wKiom1NGE7vCKAf2AAGcj0DjXhA542.jpg


打开源码找到对应的 strftime 函数,然后一路跟进去,最后终于找到了罪魁祸首!尼玛居然有一行 ASSERT!

wKioL1NGFTjCdcz2AACDetC1xO0975.jpg


wKiom1NGFWLR78UTAAENqvyPvY0744.jpg


wKioL1NGFTqB5hGWAADWSU0zmYQ909.jpg


wKioL1NGFTvh5QwBAAGS5yYMyCI589.jpg


最后就因为这个ASSERT,我们的服务端光荣的挂了,而且我们外网的服务端就用的是debug版本,不过幸好 glibc 的库下不存在这个问题。


既然都看到这里了,我就顺带对比了一下,vs这个版本的CRT库里strftime能够支持的字符和标准有什么区别:

CRT能够支持的字符有:aAbBcdHIjmMpSUwWxXyYZz%'\004''\015'

而最新的c和c++可以支持的果然更多,可以在cplusplus.com对比一下:http://www.cplusplus.com/reference/ctime/strftime/