繁体   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