今天項目發生了一件很有意思的事情,案件很離奇。案件的經過是這樣的:
案件經過
我們在寫一個庫對接硬件平臺和第三方模塊,庫封裝了一些平臺有關的接口給第三方使用,但是當我們把對接第三方模塊的時候對方服務器報錯了,服務器方反饋上報的某個參數有誤。然後我們發現參數的確有誤:
//本來參數在終端應該是這麼顯示的
//printf("abc=[%s]", efg)
abc=[efg]
//但是結果是這樣的
]bc=[efg
但是我的接口只有兩行代碼不可能有錯吧:
int xuean_get_abc(char* efg) {
const char* value = my_database_get_safe("abc", "");
if(isNull(value))
return -1;
strcpy(efg, value);
return 0;
}
這種業務代碼除了可能緩衝區溢出之外,應該沒什麼什麼太大的問題吧。爲什麼那個”]”莫名其妙跑到了最前面去了呢,我一開始懷疑字符串太長緩衝區溢出,但是想想,不可能啊,覆蓋的結果也不應該是這樣的呀。於是覺得肯定是數據庫返回的東西有問題了。
//show all data
123=456
abc=efg
x=z
沒問題呀看上去很完美啊,那就奇怪了,爲什麼那個”]”跑去前面去了呢,它長腿了嗎?但是我堅信肯定是它有問題了,那乾脆把整個數據的內存16進制打出來,於是看到這樣的結果:
65 66 67 D 0
果然在NULL和efg之間還有一個“D”,對應“\r“,單獨的”\r”可是回到最左邊的意思,怪不得那個”]”跑回去,但是這一切是怎麼發生的呢,從羣衆中來還得回羣衆中去啊,乾脆看看那個kv數據庫的代碼:
fgets(buf, MAX_BUF_LEN, file);
//xxxx進行一些長度判斷
buf[strlen(buf) - 1] = '\0';//是要去掉換行符的重要
//於是buf高高興興的塞入到數據庫中去了
這段代碼看上去很完美啊,一個字符都沒有多餘。但是突然發現那個精闢的地方有點奇怪,於是用二進制編輯器一看,果然這個文件是在windows下編輯的,呵呵,呵呵,呵呵,windows和linux的換行符好像有點不太一樣吧,對的,你不能假定換行符就是”\n”,因爲它有可能還是”\r\n”,哦哦哦,\n去掉了不久只剩下\r了嘛。於是問題就愉快的解決了。
看完這個故事我明白了,對待換行符要小心啊,不然會很慘的