靜態編譯的EXE重定位項不能多於65535個

去年(2014年)9月份,我收到來自網友的錯誤報告,說易語言代碼行數超過4萬,靜態編譯的EXE啓動時異常崩潰。他那個源碼是在一個子程序裏面寫了4萬多行代碼,每一行都調用Win32 API函數MessageBoxA。

我(Liigo)當時仔細檢查了易語言5.x靜態編譯相關的源代碼,分析後得出初步結論:整個易程序就一個代碼段(.text),編譯成OBJ也位於一個Section內,而其中最多只能有65535個重定位項(WORD NumberOfRelocations)。如果代碼過多,重定位數目過多(程序內的函數、變量、常量都可能需要重定位項),這個WORD值(16bits無符號整數)很可能會溢出,導致EXE重定位不正常,進而導致指針訪問越界並且崩潰。詳見MSDN上對結構體IMAGE_SECTION_HEADER 的定義。

如果需要修改的話,可能需要在易語言靜態編譯時,拆分成多個代碼段,靜態鏈接也要更新做相應的處理。但是這樣也仍然不能解決本質問題:如果程序員執意要在同一個函數/子程序裏寫幾萬行代碼,導致生成過多的重定位項,編譯鏈接系統也是沒有辦法的,總不能把這個函數定義切分放到不同的Section去吧?

所以這個問題根本就是無解。歸根揭底是C/C++編譯鏈接系統COFF格式OBJ文件結構設計不合理。不止易語言程序,它們Visaul Studio編譯出來的C/C++程序同樣也會受到該問題的困擾。要解決,只能程序員去解決,把函數/子程序分割,提煉出小的函數/子程序,通過這種方式減少重定位項的數目。但無論如何,易語言把整個程序放進同一個Section內,是一種取巧,並且讓問題更容易暴露出來:C/C++程序是每個函數不能重定位項超量,易語言程序是整個程序不能重定位項超量。

我當時也跟吳濤吳總進行過溝通。他基本認可我的分析結果,同時也認爲這類情況是一種特例,易語言沒有爲此更新的必要。

前幾天易語言論壇又有人遇到了類似的錯誤。我聯想到之前的情況,寫出本文算是一個交待。就是這樣,謝謝。


----


續篇:《再議易語言靜態編譯重定位數目過多》 2018-06-28 by Liigo.


發佈了275 篇原創文章 · 獲贊 442 · 訪問量 244萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章