- 論壇徽章:
- 0
|
本帖最后由 大眾推薦 于 2014-12-03 14:48 編輯
話說。。。。2年前開始寫的一個服務器程序,一年前上線,跑了一整年,沒有掛過,前段時間剛小得意了一下。。。
結(jié)果,3周前,悲劇了。。
在過去3周里,掛了8,9次。。。。!
由于是跑在公網(wǎng)上正處于服務期的,加上很久沒怎么看過那份代碼。。。再加上自己近來比較忙,也懶。。。。。種種原因。。。。
反正斷斷續(xù)續(xù)的跟了3,4天,根本不知道是怎么回事。。。。。
而且自己記得最近沒怎么改這份代碼。。。
從3天前開始,實在是無法容忍了,于是乎gdb,strace什么的都用上了,雖然coredump大致定位了位置并提示是訪問了非法內(nèi)存,
但仔細看了該部分的代碼還是沒有找到具體的問題。。。。
可以肯定的是,出現(xiàn)問題的哪行代碼是很久沒改過了。。。
反復閱讀了這部分代碼,實在是沒問題。。。而且這部分代碼跑了1整年了,都沒有CRASH過。。。
這不科學。。。。!
仔細回想,大概在1個多月前,曾經(jīng)嘗試優(yōu)化一下HASH TABLE。。。。
于是,看了一下這部分代碼,也對比了一下之前的版本。。。。還是沒有發(fā)現(xiàn)代碼有問題。。。。
不過aaaaa.c 有類似這樣的一個地方:
struct A* a (void)
{
#if XXX
return aa();
#else
return bb();
#endif
}
其中,之前代碼只有 aa(),其他函數(shù)也只是直接調(diào)用 aa();
而 bb()是為了測試某一樣東西加而加的,
而為了這個測試,a()也是后來加的。
由于之前吃過一次虧,所以趕緊找aaaaa.h來看,果然是沒有聲明a(void)!!!!!
-----------------------------------------------------
背景交代完畢,
A.由于a()返回的是一個malloc()出來的內(nèi)存指針。
B.我沒有在頭文件中聲明函數(shù)的返回類型(一般不會出現(xiàn)這種不聲明返回類型的情況,除非是。。。有時候太HIGH了,根本就不記得了。。,而自己又不是每次都會清空編譯時候的WARNING)。
C.C返回的默認指針,是只有32BIT的。前面的32BIT會自動CUT掉。
D.跑的服務器是64BIT的。
于是乎,當某個時刻malloc()出來的內(nèi)存地址,其前面的32BIT不全為0的時候,而系統(tǒng)已經(jīng)CUT掉了前面的32BIT,那么剩下了的地址就肯定不是我們想要的。。。。
或者說,在linux(UBUNTU AMD 64)中,調(diào)用隱式聲明的API,返回默認是一個32位的INT,而接收這個返回值的時候,會轉(zhuǎn)換這個返回值為指針,并自動補齊高32BIT的值
(貌似是,如果返回值的最高位是1,則全部補0XFFFFFFFF,如果返回值的最高位為0,則全部補0)
所以,當返回的地址第31-63 BIT(不是第32BIT開始,而包括31)不全為0的時候,自動補齊得出的地址,就肯定不對。。。這個時候去訪問,就掛了。。。
-----------------------------------------------------
告誡各位新人,以后寫代碼,千萬不要偷懶。。。
1.不可不聲明全局函數(shù)。特別地,當返回值是一個指針的時候,+你跑的是64位的系統(tǒng)的時候。。。。。
2.不可放過編譯時候的任何一個warning.當然,-Wall是必須的。
|
|