memory-management - 向量函数的分配是原子的吗?(无法理解错误)
问题描述
我从程序中遇到了分段错误,我知道出了点问题,因为我使用了一个未分配的参数,但我并不真正理解错误的内部工作原理:
program MWE
implicit none
integer, allocatable :: b(:)
call S(b)
contains
subroutine S(a)
integer, intent(out) :: a(:)
a = F(10) !I was expecting the error here
! but in the assigment not inside
! the function call.
end subroutine
function F(n) result(v)
integer, intent(in) :: n
integer :: v(n)
print*, "Now comes the error"
v = 1 !here, in this assignment
print*, "We nevet get here"
end function
end program
我知道我将变量a声明为allocatable,并且我知道我将它传递给子例程 S 而不分配它。
但是我希望函数F可以正常工作,因为它被给定N,因此它知道v的大小。我希望分段错误出现在完成F之后,但在其输出分配给a之前。
鉴于我在函数F中遇到错误,我误解了一些内部工作,但我不知道是什么。
这是执行输出:
Now comes the error
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7f1bff9f28b0 in ???
#1 0x7f1bff9f1ae3 in ???
#2 0x7f1bff66c83f in ???
at /build/glibc-vjB4T1/glibc-2.28/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0
#3 0x562fc494c262 in ???
#4 0x562fc494c3d3 in ???
#5 0x562fc494c30b in ???
#6 0x562fc494c40c in ???
#7 0x7f1bff65909a in __libc_start_main
at ../csu/libc-start.c:308
#8 0x562fc494c0b9 in ???
#9 0xffffffffffffffff in ???
Segmentation fault
解决方案
对于该函数调用,gfortran 将一个隐藏参数传递给函数,告诉函数它应该将函数的结果放在内存中的哪个位置。a
该隐藏参数指定与子例程中的虚拟参数关联的存储。该存储是无效的,因为与 dummy 关联的实际参数a
尚未分配,因此函数尝试将其结果放入的存储是无效的,因此您会在函数内部看到访问冲突。
与赋值语句相关的动作隐含在让函数直接写入赋值左侧事物的存储中。
不同的编译器(或相同的编译器,对于具有不同特征的函数调用或赋值语句)将以不同的方式实现这一点 - 例如,函数可能会写入调用代码设置然后复制的临时文件,或缓冲区可能会在调用代码随后需要释放的函数内部分配。
您可以通过检查程序集(将 -S 添加到命令行)或中间表示之一(例如 -fdump-tree-original)来检查 gfortran 编译器如何实现您的程序
推荐阅读
- leaflet - MediaWiki 中的自定义传单地图
- asp.net-core - ASP.NET Core Identity 2:User.IsInRole 总是返回 false
- javascript - Chart.js 条形图中具有不同 yAxes 的相同数据集
- android - 错误:捆绑失败 - 尝试解析模块“react-native-firebase”时
- python - 地图上的 Python 多处理
- c# - 显示部分消息内容
- java - 从 HTTP 消息中查找下载的文件类型
- java - 如何在 lambda 表达式(JAVA)中使用 try catch?
- string - 尝试匹配字符串时没有触发 if 语句
- android - 从数据库中检索数据的响应延迟给我空值