pointers - 64 位 gcc 代码中的 32 位指针溢出 - 编译失败

标签 pointers gcc compiler-errors fortran gfortran

我正在运行 Yosemite 的 Mac(2.2 GHz Intel Core i7)上使用 gFortran 编译一个非常大的旧版 Fortran 90 代码(尖叫)。 (gFortran V5.1.0) 我有 16 GB 的 RAM。该代码是内存密集型的,我正在尝试增加数组大小以解决更大的问题。我已经维护代码超过 10 年,现在重写 200,000 行代码不是一个选择。当我通过改变整数“max_nodes”小心地增加二维矩阵(am(max_nodes,max_nodes))和几个一维向量(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):从 _main_loop_ (0x10000E120) 到 _main_loop_ 中的 _a.4206 (0x180034380),来自screaker64.a(main_loop.o) 架构 x86_64
collect2:错误:ld 返回 1 个退出状态

在此错误消息中,main_loop 是screamer 中的核心求解器子例程,用于填充和求解大型矩阵。在这个子程序中,定义了大的 real*8 矩阵和 real*8 向量。

此注册指令指针 (RIP) 错误在 Web 上多次出现。到目前为止,这些可用信息并没有帮助我解决我的问题。注意:有符号的 4 字节整数限制为 2,147,483,647,因此该错误似乎与使用 32 位指针直接相关。

gFortran 编译器选项包括 -mcmodel=medium 应该将指针指向 64 位。 -m64 无效。达到指针限制时,主矩阵和向量使用的总内存大于 2.4 GB。令人困惑的是代码完全是 64 位的,所以我没想到会有 32 位指针。请参阅下面的 64 位检查。

rbspielman$ 文件尖叫器64

尖叫64:Mach-O 64 位可执行 x86_64

主矩阵和向量都是实数*8(64位)。所有大型数组都直接在这一子程序中声明,并且不共同放置。

所有其他共同变量均按大小排序。实* 8,实,整数,字符。

简单的测试程序表明没有基本的内存限制。我可以轻松地将静态数组定义为 > 10 GB,而不会出现问题。较大的数组也可以工作,但最终会使用虚拟内存并按预期减慢速度。

显然存在某种内存或指针大小限制,但我无法弄清楚。代码矩阵求解器非常庞大,更实际的测试程序会很乏味。

(我还在 Ubuntu LINUX 中编译了screaser,没有出现与 Mac 相同的数组限制。Windows 8 中的编译在通常的 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)

关于pointers - 64 位 gcc 代码中的 32 位指针溢出 - 编译失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30903310/

相关文章:

c++ - C语言中如何使用内存地址?它们是十六进制还是无符号整数?

遍历列表时出现 C 段错误

boost - Clang不编译g++项目

java - Eclipse Java : “The import com.jidesoft cannot be resolved”

Visual C++ 编译错误

java - 我的国际象棋程序的线程 "main"java.lang.NullPointerException 中出现异常

C - 这个变量的类型是什么?

c - 奇怪的 gcc 警告和 sanitizer 崩溃

gcc - gcc 和 pthreads 的 undefined reference 错误 _dl_stack_flags

c++ - 如何获取字符串中所有发现的 boost::regex 模式的位置?