MingW的GCC / G ++在构建具有大型全局或静态数据的应用程序时给出了重定位错误。
Understanding the x64 code models
使用x64对x64的代码和数据进行引用 指令相对(在x64用语中相对于RIP)寻址模式。 这些指令中RIP的偏移量限制为32位。
小代码模型向编译器承诺32位相对偏移 对于编译中的所有代码和数据引用应该足够了 宾语。另一方面,大型代码模型告诉它不要制作 任何假设并使用绝对64位寻址模式代码和 数据参考。为了让事情更有趣,还有一个 中间道路,称为媒体代码模型。
对于下面的示例程序,尽管添加了选项-mcmodel = medium或-mcmodel = large,但代码无法编译
#define SIZE 16384
float a[SIZE][SIZE], b[SIZE][SIZE];
int main(){
return 0;
}
gcc -mcmodel=medium example.c fails to compile on MingW/Cygwin Windows, Intel windows /MSVC
答案 0 :(得分:2)
偏移量限制为32位,但这是签名偏移量。所以在实践中,你实际上只限于2GiB。您问为什么这是不可能的,但您的阵列单独的大小是2GiB,数据段中除了您的阵列之外还有其他东西。 C是一种高级语言。您可以轻松地定义主要功能,并且您可以免费获得所有其他内容 - 标准输入和输出等.C运行时为您实现此功能,所有这些都消耗了堆栈空间和空间你的数据段。例如,如果我在x86_64-pc-linux-gnu上构建它,我的.bss
大小大小为0x80000020 - 另外32个字节。 (我已经从大脑中删除了体育信息,所以我不记得这些是如何布局的。)
我不太了解各种机器型号,但是注意到x86_64指令集甚至不包含指令(我很清楚,虽然我不是x86汇编专家,但是要访问超出有符号32位值的任何寄存器相对地址。例如,当你想在堆栈上填充那么多东西时,gcc必须做一些奇怪的事情,比如这个堆栈指针分配:
movabsq $-10000000016, %r11
addq %r11, %rsp
您不能addq $-10000000016, %rsp
,因为它不仅仅是签名的32位偏移量。这同样适用于RIP相对寻址:
movq $10000000016(%rip), %rax # No such addressing mode