移植C/C++到嵌入式Linux下程序崩潰的問題

最近將自己開發的SIP協議棧移植到ARM芯片下的嵌入式Linux,遇到一個奇怪問題,這篇小文簡要記錄解決過程。

相同的代碼在windows下、CentOS Linux下都正常,交叉編譯到ARM芯片的64位Linux下總是崩潰,估計堆棧、內存被破壞,用Valgrind沒辦法定位到具體的出錯位置。經過多次用最原始的printf()跟蹤,發現和md5加密函數有關,篩查了代碼死活也沒發現錯誤。如此折騰了將近一週,神經高度緊張。

後來仔細分析相關的源代碼,終於發現問題所在。

協議棧用到一個md5的函數庫,這個庫比較古老,Dos時代就存在。其中的頭文件md5.h有問題:

#ifdef __alpha

typedef unsigned int uint32;

#else

typedef unsigned long uint32;

#endif

Dos時代(或windows NT 3.1時代),alpha芯片是32位的,因此定義一個32位無符號整數,用unsigned int,而intel的286之類的芯片int類型是16位的,所以32位無符號整數需定義爲unsigned long。

到了現在的64位時代,這些就有問題了。

在windows下:int - 4字節32位,long - 4字節32位,long long - 8字節64位

在linux下:int - 4字節32位,long - 8字節64位,long long - 8字節64位

上述定義,非_alpha,32位無符號整數被定義爲typedef unsigned long uint32,在windows下沒問題,在linux下是有問題的,實際上成了64位。很多因此定義的緩衝區,在操作時就可能出錯。

也許會問,同樣Linux,爲何CentOS下沒問題呢?那是因爲Intel和ARM芯片的內存佈局不一樣,ARM會立即暴露而已。

後來將上述定義統一改爲(反正不可能16位時代了):

typedef unsigned int uint32;

重新編譯後,程序就非常穩定了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章