天天看點

靜态編譯的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.

繼續閱讀