去年(2023年)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.
靜態鏈結 重定位
在幾年前第一次學c語言時,按照書上給的示例,在vc6.0中寫了helloworld程式,然後按照書上的教程,進行編譯,鏈結,最後執行程式,就能在輸出視窗上看到helloworld。對於乙個用ide寫 的人來說,需要編譯鏈結才能生成可執行檔案這是乙個常識,那麼編譯鏈結到底做了乙個什麼樣的事情呢?因為我...
程式的鏈結與裝入(動 靜態重定位)
多道程式環境下,程式是併發執行的,所以要使程式執行,必須先為之建立程序,而建立程序的第一件事就是將程式和資料裝入記憶體 源程式經過編譯後,得到一組目標模組,再利用 鏈結程式 將這組目標模組鏈結起來,形成乙個完整的裝入模組 即可執行檔案 相對位址進行修改 變化以後還是相對位址 位址都變為相對最上層模組...
程式的鏈結與裝入(動 靜態重定位)
多道程式環境下,程式是併發執行的,所以要使程式執行,必須先為之建立程序,而建立程序的第一件事就是將程式和資料裝入記憶體 即 源程式經過編譯後,得到一組目標模組,再利用 鏈結程式 將這組目標模組鏈結起來,形成乙個完整的裝入模組 即可執行檔案 相對位址進行修改 變化以後還是相對位址 位址都變為相對最上層...