前段時間,在給我們遊戲服務器寫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函數:
打開,因爲我們的服務端編的都是debug版本,vs編debug版默認使用的多線程的那個debug版本的庫:
打開源碼找到對應的 strftime 函數,然後一路跟進去,最後終於找到了罪魁禍首!尼瑪居然有一行 ASSERT!
最後就因爲這個ASSERT,我們的服務端光榮的掛了,而且我們外網的服務端就用的是debug版本,不過幸好 glibc 的庫下不存在這個問題。
既然都看到這裏了,我就順帶對比了一下,vs這個版本的CRT庫裏strftime能夠支持的字符和標準有什麼區別:
CRT能夠支持的字符有:aAbBcdHIjmMpSUwWxXyYZz%'\004''\015'
而最新的c和c++可以支持的果然更多,可以在cplusplus.com對比一下:http://www.cplusplus.com/reference/ctime/strftime/