簡體   English   中英

64位gcc代碼中的32位指針溢出-編譯失敗

[英]32-bit pointer overflow in 64-bit gcc code - fails in compile

我正在運行優勝美地的Mac(2.2 GHz Intel Core i7)上使用gFortran編譯非常大的舊版Fortran 90代碼(尖叫)。 (gFortran V5.1.0)我有16 GB的RAM。 該代碼占用大量內存,我正嘗試增加數組大小以解決更大的問題。 我將代碼維護了10年以上,現在無法重寫200,000行代碼。 當我通過改變整數“ max_nodes”來小心地增加2-D矩陣(am(max(max_nodes,max_nodes))和幾個1-D向量(RHS(max_nodes)和a(max_nodes * 2))的大小時,我最終得到編譯期間的32位指針限制(4字節無符號整數限制)。 見下文。

最后一節的布局:

__TEXT/__text addr=0x100001390, size=0x0006B9CB, fileOffset=0x00001390, type=1
__TEXT/__text_startup addr=0x10006CD60, size=0x00000041,    fileOffset=0x0006CD60, type=1
__TEXT/__text_exit addr=0x10006CDB0, size=0x00000031, fileOffset=0x0006CDB0, type=1
__TEXT/__stubs addr=0x10006CDE2, size=0x00000252, fileOffset=0x0006CDE2, type=28
__TEXT/__stub_helper addr=0x10006D034, size=0x000003EE, fileOffset=0x0006D034, type=32
__TEXT/__cstring addr=0x10006D428, size=0x0000CFCB, fileOffset=0x0006D428, type=13
__TEXT/__const addr=0x10007A400, size=0x00008F00, fileOffset=0x0007A400, type=0
__TEXT/__eh_frame addr=0x100083300, size=0x0000DCF8, fileOffset=0x00083300, type=19
__DATA/__got addr=0x100091000, size=0x00000060, fileOffset=0x00091000, type=29
__DATA/__nl_symbol_ptr addr=0x100091060, size=0x00000010, fileOffset=0x00091060, type=29
__DATA/__la_symbol_ptr addr=0x100091070, size=0x00000318, fileOffset=0x00091070, type=27
__DATA/__mod_init_func addr=0x100091388, size=0x00000010,  fileOffset=0x00091388, type=33
__DATA/__mod_term_func addr=0x100091398, size=0x00000008, fileOffset=0x00091398, type=34

__DATA/__const addr=0x1000913A0, size=0x000007C8, fileOffset=0x000913A0, type=0
__DATA/__static_data addr=0x100091B68, size=0x00000003, fileOffset=0x00091B68, type=0
__DATA/__data addr=0x100091B80, size=0x000003E0, fileOffset=0x00091B80, type=0
__DATA/__bss4 addr=0x100091F60, size=0x00000018, fileOffset=0x00000000, type=25
__DATA/__bss5 addr=0x100091F80, size=0x00020000, fileOffset=0x00000000, type=25
__DATA/__bss3 addr=0x1000B1F80, size=0x00000028, fileOffset=0x00000000, type=25
__DATA/__pu_bss2 addr=0x1000B1FA8, size=0x00000008, fileOffset=0x00000000, type=25
__DATA/__bss2 addr=0x1000B1FB0, size=0x00000024, fileOffset=0x00000000, type=25
__DATA/__pu_bss5 addr=0x1000B1FE0, size=0x0000024C, fileOffset=0x00000000, type=25
__DATA/__pu_bss4 addr=0x1000B2230, size=0x00000018, fileOffset=0x00000000, type=25
__DATA/__common addr=0x1000B2260, size=0x000020D8, fileOffset=0x00000000, type=25
__DATA/__zo_bss3 addr=0x1000B4338, size=0x00000021, fileOffset=0x00000000, type=25
__DATA/__huge addr=0x1000B4360, size=0x984EB80C, fileOffset=0x00000000, type=25

ld:32位RIP相對參考超出范圍(2147639505最大值為+/- 4GB):從smain_loop_(0x10000E120)到_main_loop_'中的_a.4206(0x180034380)從screamer64.a(main_loop.o)的架構x86_64 collect2 :錯誤:ld返回1退出狀態

在此錯誤消息中,main_loop是Screamer中的核心求解器子例程,該子例程填充並求解大型矩陣。 在此子例程中,定義了大的real * 8矩陣和real * 8向量。

Web上多次記錄此寄存器指令指針(RIP)錯誤。 到目前為止,這些可用信息並沒有幫助我解決問題。 注意:帶符號的4字節整數限制為2,147,483,647,因此該錯誤似乎與使用32位指針直接相關。

gFortran編譯器選項包括-mcmodel = medium,應將指針指向64位。 -m64沒有作用。 達到指針限制時,主矩陣和向量使用的總內存大於2.4 GB。 令人困惑的是該代碼是完全64位的,因此我不希望使用32位指針。 請參閱下面的64位檢查。

rbspielman $文件screamer64

screamer64:Mach-O 64位可執行文件x86_64

主矩陣和向量均為real * 8(64位)。 所有大數組都直接在此子例程中聲明,並且不放在公共位置。

所有其他共同變量按大小排序。 real * 8,real,int,char。

簡單的測試程序表明沒有基本的內存限制。 我可以輕松地將靜態數組定義為> 10 GB,而不會出現問題。 較大的陣列也可以使用,但最終會使用虛擬內存並按預期速度變慢。

顯然存在某種內存或指針大小限制,但我只是無法弄清楚。 代碼矩陣求解器非常龐大,更加實際的測試程序會很乏味。

(我也可以在Ubuntu LINUX中編譯尖叫程序,而不會出現與Mac相同的數組限制的問題。Windows8中的編譯在通常的2 GB內存限制下失敗,而在指針限制下失敗。)

建議將不勝感激。

我只是在運行10.11.5的Mac中遇到了與GNU Fortran(GCC)5.1.0相同的問題,但是OP提供的解決方案對我不起作用。

但是,我確實找到了一個解決方案:在系統修剪了我那行人慣用的遺留代碼之后,我發現每個數組都必須顯式地填充一些東西。 您無法開始在代碼中填充它。 我知道這聽起來很愚蠢,但是在我執行任何I / O或其他工作之前,一旦我用0.0初始化了每個“真實”數組(32位,這是舊代碼),它就會毫無疑問地鏈接在一起。

而且,是的,與OP一樣,我的代碼一直有效,直到更改了數組的大小。

可行的原因可能在此錯誤報告的內容中: https : //gcc.gnu.org/bugzilla/show_bug.cgi?id=63793,但我還不足以告訴您如何提出更好的建議解決方法。 我唯一的猜測是,在開始時初始化每個陣列都會有利於GOT而不是RIP。 (什么時候可以解決?我只是不知道如何將其推進,並且錯誤報告的發布日期為2014-11-09)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM