gfortran 傻瓜版: mcmodel=medium 到底是做什么的?

2023-11-22

我有一些代码在编译时出现重定位错误,下面是说明该问题的示例:

  program main
  common/baz/a,b,c
  real a,b,c
  b = 0.0
  call foo()
  print*, b
  end

  subroutine foo()
  common/baz/a,b,c
  real a,b,c

  integer, parameter :: nx = 450
  integer, parameter :: ny = 144
  integer, parameter :: nz = 144
  integer, parameter :: nf = 23*3
  real :: bar(nf,nx*ny*nz)

  !real, allocatable,dimension(:,:) :: bar
  !allocate(bar(nf,nx*ny*nz))

  bar = 1.0
  b = bar(12,32*138*42)

  return
  end

编译这个gfortran -O3 -g -o test test.f,我收到以下错误:

relocation truncated to fit: R_X86_64_PC32 against symbol `baz_' defined in COMMON section in /tmp/ccIkj6tt.o

但如果我使用的话它会起作用gfortran -O3 -mcmodel=medium -g -o test test.f。另请注意,如果我使数组可分配并在子例程中分配它,它就会起作用。

我的问题是到底是什么-mcmodel=medium做?我的印象是代码的两个版本(带有allocatable数组和没有数组的数组)或多或少是等效的......


Since bar相当大,编译器会生成静态分配而不是在堆栈上自动分配。静态数组是用以下命令创建的.comm汇编指令,在所谓的 COMMON 部分中创建分配。来自该部分的符号被收集,同名符号被合并(减少到一个符号请求,其大小等于所请求的最大大小),然后其余部分被映射到大多数可执行格式的 BSS(未初始化数据)部分。使用 ELF 可执行文件.bss部分位于数据段中,就在堆的数据段部分之前(还有另一个由匿名内存映射管理的堆部分,它不驻留在数据段中)。

随着small内存模型 32 位寻址指令用于对 x86_64 上的符号进行寻址。这使得代码更小并且速度更快。使用时的一些汇编输出small内存模型:

movl    $bar.1535, %ebx    <---- Instruction length saving
...
movl    %eax, baz_+4(%rip) <---- Problem!!
...
.local  bar.1535
.comm   bar.1535,2575411200,32
...
.comm   baz_,12,16

这使用 32 位移动指令(5 个字节长)来放置bar.1535符号(该值等于符号位置的地址)到低32位RBX寄存器(高 32 位清零)。这bar.1535符号本身是使用分配的.comm指示。内存为baz随后分配 COMMON 块。因为bar.1535非常大,baz_从开始到结束超过 2 GiB.bss部分。这在第二个中提出了问题movl指令,因为非 32 位(有符号)偏移量来自RIP应该用来解决b变量,其中的值EAX必须搬进去。这仅在链接期间检测到。汇编器本身不知道适当的偏移量,因为它不知道指令指针的值是多少(RIP)将是(它取决于加载代码的绝对虚拟地址,这是由链接器确定的),所以它只是放置一个偏移量0然后创建一个类型的重定位请求R_X86_64_PC32。它指示链接器修补以下值0与实际的偏移值。但它不能这样做,因为偏移值不适合有符号的 32 位整数,因此会退出。

随着medium内存模型看起来像这样:

movabsq $bar.1535, %r10
...
movl    %eax, baz_+4(%rip)
...
.local  bar.1535
.largecomm      bar.1535,2575411200,32
...
.comm   baz_,12,16

首先,使用 64 位立即数移动指令(10 字节长)来放置表示地址的 64 位值bar.1535进入寄存器R10。内存为bar.1535符号是使用分配.largecomm指令,因此它结束于.lbssELF 可执行文件的部分。.lbss用于存储可能不适合前 2 GiB 的符号(因此不应使用 32 位指令或 RIP 相对寻址来寻址),而较小的东西则用于存储.bss (baz_仍然使用分配.comm并不是.largecomm)。自从.lbss部分放置在.bssELF 链接器脚本中的部分,baz_使用 32 位 RIP 相关寻址不会最终导致无法访问。

所有寻址模式均在System V ABI:AMD64 架构处理器补充。这是一本厚重的技术读物,但对于真正想了解 64 位代码如何在大多数 x86_64 Unix 上工作的人来说,这是必读的。

When an ALLOCATABLE而是使用数组,gfortran分配堆内存(考虑到分配的大小,最有可能实现为匿名内存映射):

movl    $2575411200, %edi
...
call    malloc
movq    %rax, %rdi

这基本上是RDI = malloc(2575411200)。从此以后的元素bar通过使用存储在中的值的正偏移量来访问RDI:

movl    51190040(%rdi), %eax
movl    %eax, baz_+4(%rip)

对于从开始时起超过 2 GiB 的位置bar,使用更复杂的方法。例如。实施b = bar(12,144*144*450) gfortran emits:

; Some computations that leave the offset in RAX
movl    (%rdi,%rax), %eax
movl    %eax, baz_+4(%rip)

此代码不受内存模型的影响,因为没有对进行动态分配的地址进行任何假设。此外,由于数组没有被传递,因此没有构建描述符。如果添加另一个采用假定形状数组的函数并传递bar对它来说,一个描述符bar被创建为自动变量(即在堆栈上foo)。如果数组是静态的SAVE属性,描述符被放置在.bss部分:

movl    $bar.1580, %edi
...
; RAX still holds the address of the allocated memory as returned by malloc
; Computations, computations
movl    -232(%rax,%rdx,4), %eax
movl    %eax, baz_+4(%rip)

第一步准备函数调用的参数(在我的示例案例中call boo(bar) where boo有一个接口将其声明为采用假定形状数组)。它移动数组描述符的地址bar into EDI。这是一个 32 位立即移动,因此描述符预计位于前 2 GiB 中。事实上,它被分配在.bss同时small and medium内存模型如下:

.local  bar.1580
.comm   bar.1580,72,32
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gfortran 傻瓜版: mcmodel=medium 到底是做什么的? 的相关文章

  • 如何测量Python中对象的内存使用情况?

    我有一个Python课程foo其中包含 数据 整数 浮点数 列表 整数 浮点数和其他对象的列表 字典 整数 浮点数 其他对象的 假设没有反向引用 循环 是否有一种简单的方法来测量一个进程的总内存使用量foo目的 本质上 我正在寻找一个递归版
  • 将结构化数据类型从 Fortran 传递到 C++ [重复]

    这个问题在这里已经有答案了 我在 Fortran 中有一个结构化类型 其中包含大量数据 包括指针 real 8 指针数据类型 我正在为某些 Fortran 例程开发 C API 我需要在对 Fortran 例程的调用之间保留该结构的内容 我
  • Mac OS X 上的 64 位程序集运行时错误:“dyld:无可写段”和“Trace/BPT trap”

    当尝试运行以下汇编程序时 globl start start pushq 0x0 movq 0x1 rax subq 0x8 rsp int 0x80 我收到以下错误 dyld no writable segment Trace BPT t
  • 段寄存器如何参与内存地址转换?

    到目前为止我所学到的有关细分的知识 虚拟地址包含段选择器和偏移量 段选择器与GDTR配合使用 查找段描述符的线性地址 段描述符保存有关所选段的信息 包括其线性地址 所以 我的问题是 根据我所读到的内容 虚拟地址被加载到段寄存器中 然后以某种
  • 使用 Fortran 90 正确读取输入文件中的注释行

    据我了解 Fortran 在从文件读取数据时 会跳过以星号 开头的行 假设它们是注释 好吧 我似乎在用我创建的一个非常简单的程序实现这种行为时遇到了问题 这是我的简单 Fortran 程序 1 program test 2 3 intege
  • python tracemalloc 模块分配统计信息何时会与 ps 或 pmap 中显示的内容不匹配?

    我正在尝试查找内存泄漏 所以我已经完成了 import tracemalloc tracemalloc start
  • 如何正确取消引用然后删除 JavaScript 对象?

    我想知道从内存中完全取消引用 JavaScript 对象的正确方法 确保删除时不会在内存中悬空 并且垃圾收集器会删除该对象 当我看这个问题时在 JavaScript 中删除对象 https stackoverflow com questio
  • Fortran 子例程返回错误值

    嘿 我正在开发一个 Fortran 程序 遇到了一个奇怪的问题 当我尝试在调用特定子例程之前直接输出数组的某些值时 我得到了正确的值 然后 我尝试在启动子例程时输出同一数组的一些值 它们都是 0 我最终在子例程之后输出数组的值 并且这些值回
  • 从 64 位 nasm 代码接收 32 位寄存器

    我正在学习 64 位 nasm 我通过执行以下操作来汇编 nasm 文件 该文件仅包含 64 位寄存器 nasm f elf64 HelloWorld nasm o HelloWorld o 并链接它执行以下操作 ld HelloWorld
  • 如果内存是字节可寻址的,为什么我们需要对齐填充?

    既然我们可以单独寻址内存的每个字节 为什么编译器要格外小心以确保结构及其成员与内存中的 32 位边界对齐 我在这里可能是错的 但是在 32 位系统上 从 0x0800 开始获取 4 个字节是不是和从 0x0801 开始获取 4 个字节一样快
  • ARC 禁止合成未指定所有权或存储的财产

    我创建了一个 property of UIColor property nonatomic UIColor color 然后我尝试合成它 synthesize color color 但我收到一个错误 ARC 禁止合成具有未指定所有权或存储
  • .NET 内存不足故障排除

    在阅读了几篇有关 NET 技术中的内存的启发性文章后 Out of Memory 不是指物理内存 https learn microsoft com en us archive blogs ericlippert out of memory
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • 如何正确处置注入的DLL线程?

    我将一个 DLL 注入到目标进程中 以在玩 MMORPG 时充当助手 当前功能将按键转换为鼠标点击 因为 MMORPG 要求用户移动鼠标才能实现某些功能 这是我所鄙视的 假设我出于某种原因想要取消注入 DLL 我该怎么做呢 这个方法干净吗
  • pandas 数据框 - 选择行并清除内存?

    我有一个大的 pandas 数据框 大小 3 GB x read table big table txt sep t header 0 index col 0 因为我在内存限制下工作 所以我对数据帧进行了子集化 rows calculate
  • 如何在fortran中调用和使用另一个子程序中的子程序?

    我正在编写一个程序 其中主程序包含许多子例程和函数 为了构造主程序的这些子程序之一 假设是子程序 A 我需要使用另一个子程序 假设是 B 我的问题是 如何调用子程序A并使用子程序B 我是初学者 我已经搜索了很多 但没有找到我清楚理解的东西
  • 创建一个引用计数的图形

    看来在 matplotlib 中创建图形的标准方法并不像我在 python 中期望的那样 默认调用fig matplotlib figure in a 循环将保留创建的所有图形 并最终耗尽内存 有quite https stackoverf
  • 如何使用 Span 和 stackalloc 创建临时小列表

    我正在阅读一些用 C 编写的代码的描述 这些代码由于在堆栈上而不是堆上分配临时数组以在非常热的循环中使用而提高了速度 它被描述为类似于 SBO 优化 有问题的对象类似于List
  • 编译器在这里做了什么,允许通过很少的实际比较来完成许多值的比较?

    我的问题是编译器在这种情况下正在做什么 它对代码的优化程度超出了我的想象 鉴于此枚举 enum MyEnum Entry1 Entry2 Entry3 27 are the same omitted for size Entry28 Ent
  • 在 C++ 中按大小零分配内存?

    int a 10 int p new int 0 p a cout lt lt p lt lt endl 在C 中 如果分配内存大小为零会发生什么 分配后 我得到有效的内存指针 并打印有效的数字 但我认为 new 运算符应该返回类似 FAI

随机推荐

  • 在 Go 中,如何在不使用 for 循环的情况下初始化数组?

    我有一个数组A布尔值 按整数索引0 to n 全部初始设置为true 我当前的实现是 for i 0 i lt n i A i true Using a for循环是最简单的解决方案 创建数组或切片将始终返回一个归零的值 哪种情况下bool
  • Python sys.path 修改不起作用

    我正在尝试修改我的 Python 文件之一中的 sys path 以获得一些 模块搜索路径中的特定库目录 这可能不是最好的方法 但 如果我在 sys path 前面插入多个路径 我的脚本不会考虑将来导入的这些路径 如果我创建一个包含我需要的
  • 如何获取 Oracle SQL 查询中错误的位置?

    如何获取查询中错误的位置 我需要获取导致错误的查询字符串中的位置 例如sqlplus可以 SQL gt insert into tbl data values 12345 2 insert into tbl data values 1234
  • ASP.Net - 从包含数据绑定的标记调用方法

    我在 ASP NET 中有一个用 C 编写的用户控件 该用户控件在代码隐藏中有一个方法 定义如下 protected string GetGreeting string name if String IsNullOrEmpty name r
  • 如何查找数组中的重复值?

    我正在 SQLite 上工作 我编写了一个查询 它返回两个数组 ItemsArray 和 CustomersIDArray 如下所示 ItemsArray Element at Index 0 Off White Element at In
  • iOS - 更新到新版本时保留旧的 sqlite 数据库

    我发现了一些其他问题 但我没有清楚地知道如何在 ios 中更新应用程序时保留旧数据库中的数据 情况1 我可以保留旧数据库吗 如果情况 1 为 是 我可以插入新列或在旧数据库中进行任何更改吗 这安全吗 如果情况 1 为 否 我可以在新数据库中
  • 在 asp.net mvc 3 中预填充 Html.TextBoxFor

    我对此很陌生 所以如果这还不够解释的话 我很抱歉 我想在 asp net mvc 3 的表单中预填充一个字段 这可行 Html TextBox CompName null new value ViewBag CompName 但是当我想用一
  • Spring boot - 如何获取运行端口和IP地址[重复]

    这个问题在这里已经有答案了 我在启动 Spring Boot 应用程序时通过 shell 脚本传递端口 想知道如何获取应用程序中的运行端口和系统IP地址以打印在日志文件中 脚本 Dcom sun management jmxremote D
  • 免费的java 3d引擎[关闭]

    Closed 这个问题是无关 目前不接受答案 适用于 java 的最佳 3D 游戏引擎是什么 我正在寻找具有良好的视觉开发工具集的东西 我已经查看了维基百科上的可用列表 http en wikipedia org wiki List of
  • ggplot 增加箱线图之间的距离

    如何避免附加箱线图 谢谢 ggplot df aes x factor time y val fill ID geom boxplot scale fill manual values c WT goldenrod3 KO steelblu
  • 设置 char* 缓冲区并中间转换为 int*

    我无法完全理解我在这里读到的内容的后果 将 int 指针转换为 char ptr 反之亦然 简而言之 这行得通吗 set4Bytes unsigned char buffer const uint32 t MASK 0xffffffff i
  • 无法在 D3 JavaScript 库中获取点击事件

    我正在使用 D3 JavaScript 库将数据显示为力定向标记 效果很好 但我无法将点击事件添加到圈子中 因此 当我单击圆圈时 我会获得对该圆圈的详细分析并将其显示在模式框中 var links source x target y typ
  • 将生成的 PIL 图像保存到 django 中的 ImageField 中

    我在用qrcode生成二维码 当购买门票或购买真实时 我想生成一个二维码图像并使用 PIL 进行一些更改 最后将修改后的画布保存到模型的Image字段中 class Ticket models Model booked at models
  • Angular ui 模式与控制器位于单独的 js 文件中

    我正在尝试制作一个可以从应用程序中的多个位置实例化的模式 从这里给出的例子 Bootstrap 的 Angular 指令模态控制器与实例化模态的控制器位于同一文件中 我想将模态控制器与 应用程序 控制器分开 索引 html
  • Inno Setup 组件的详细描述

    我正在使用 Inno Setup 构建安装 并使用组件部分来允许最终用户选择要安装的可选项目 其中一些项目需要更长的描述 以便用户有足够的信息来智能地选择它们 有没有办法在某处添加更深入的描述 此解决方案仅使用正确的 Inno Setup
  • 为什么 Qt Creator 3.0.0 欢迎模式在 VM 中不起作用?

    我最初在我的 Win7 64 位机器上安装了 Qt 5 20 和 Qt Creator 3 0 它运行得很好 然后我想将其安装到Win7 32位虚拟机中 使用VirtualBox 在虚拟机中 我从 qt project org 网站开始并下
  • javascript更改获取参数而不重定向[重复]

    这个问题在这里已经有答案了 如何只更改 get 参数而不重定向 parent location search after 20 ok that changes but also redirect to the new page 有什么解决办
  • 如何使用 pip 卸载可编辑包(使用 -e 安装)

    我已经用 e 安装了一些软件包 gt pip install e git https github com eventray horus git 2ce62c802ef5237be1c6b1a91dbf115ec284a619 egg ho
  • 替代 MySQL 的 UUID 版本 1 功能?

    Context Web 应用程序 PHP 5 MySQL 5 0 91 问题 我最近从使用自动递增整数改为使用 UUID 作为某些表的主键 通过 MySQL 生成 UUID 时UUID 功能 它们彼此非常相似 uuid 1e5988da a
  • gfortran 傻瓜版: mcmodel=medium 到底是做什么的?

    我有一些代码在编译时出现重定位错误 下面是说明该问题的示例 program main common baz a b c real a b c b 0 0 call foo print b end subroutine foo common