我們在使用C語言編程時,卻常常要考慮超出32767這個數(shù)值的數(shù)要怎么放(習慣新用int)。 而當我們使用的語言越來越抽象,越來越不需要接觸到底層時。整型的長度好像再也不會成為我們考慮的問題。Objective-C語言中NSInteger是這樣定義的。
typedef long NSInteger;
typedef unsigned long NSUInteger;
typedef int NSInteger;
typedef unsigned int NSUInteger;
由于Objective-C語言是基于C語言實現(xiàn)的,所以NSInteger既C語言的long 在32位機中最大正整數(shù)是2147483647。64位中就更不用擔心位數(shù)不夠用了(據(jù)說QQ曾經(jīng)面臨過QQ號用盡的問題)
1.問題的背景
昨天在YY狼人殺項目開發(fā)中。就出現(xiàn)了一個這樣的BUG。
具體情況是,我們需要向服務器請求一個URL,這個URL是一個字符串并且服務器幫我們填進去了stringFormat的格式控制。
URL如下:
@"http://lanxxxxx.xx.com/x/xxxxx/index.html?gameid=%d&uid=%d&start_time=%d"
我們客戶端需要將gameid,uid,start_time三個參數(shù)傳入,然后使用webView打開這個URL。
NSString *str = [NSString stringWithFormat:URL,gameId,uid,startTime];
[MFWebViewController showWebViewController:str title:@""];
這里有一個隱患,既格式化字符串傳入的參數(shù)是%d在Objective-C語言中是代表C語言的整型,而我們的三個參數(shù)都是uint_64。之后的問題也是由這個隱患引起的。
2.問題的出現(xiàn)
昨天測試拿了一臺iPhone5手機過來向我提一個bug,本身應該正確顯示的starTime在webView上不能正常顯示,顯示為2018年8月。而我iOS原生頁面顯示正常。第一反應是web頁面解析不對。讓測試去找前端開發(fā)。后面測試告訴我,所有的手機(包括iOS安卓)都能顯示正常,只有這一臺iPhone5顯示不正常(我當時的內心(╯﹏╰))。
3.問題定位
開始排查。
web告訴我我這邊傳過去的starTime確實不對。而這個值是服務器提供的。依次列出可能的原因:
- 測試人員手機的問題。
- 在模擬器上使用iPhone5跑了一下,發(fā)現(xiàn)問題復現(xiàn)了。那就應該不是一臺手機有問題,是所有的iPhone5都不對
這個可能性排除
- 在某個地方修改過數(shù)值。
- 通過觀察代碼和斷點測試發(fā)現(xiàn),一直到push進webview頁面,gameid的值都沒有改變,但是輸出拼接的URL時發(fā)現(xiàn)在URL中gameid的值與本身傳入的gameid的值不符。于是定位到出錯位置為:
[NSString stringWithFormat:URL,gameId,uid,startTime];
4.出錯原因
由于URL是服務器傳下來的,打印URL發(fā)現(xiàn)URL中使用%d,也既傳入數(shù)據(jù)為C語言的整型。在iPhone5s及以上的機型為64位機。在C語言中int有幾種長度,32位機為16位,64位機為32位。而傳入的startime是一個時間戳,只有前32位有數(shù)據(jù)。所以iPhone5s及以上數(shù)據(jù)沒有問題,而iPhone5是32位機,只讀取了16位數(shù)據(jù)另外16位應該是寄存器中殘留的數(shù)據(jù)。
5.問題解決
找到問題的原因就可以著手解決。最簡單的方案是讓服務器傳過來用%llu作為格式控制。這樣我代碼也不需要修改。但是安卓反饋安卓不支持%llu格式控制。安卓的%d就包括了所有整型(這種兩端不一致的問題也是很蛋疼)。最后協(xié)商,該URL不由服務器下發(fā),寫死在本地。問題得到解決。