【发布时间】:2015-11-27 18:21:19
【问题描述】:
我不明白为什么一个简单的 fortran 程序会在 Ubuntu 14.04 Trusty 下导致分段错误,但在 Ubuntu 12.04 Precise 下却可以正常工作。我认为通过两次使用 WRITE 命令的 ERR 选项来隔离它:
PROGRAM WRITESEGF2
WRITE (*,'(I8)',ERR=40) 3.14
40 CONTINUE
WRITE (*,'(I8)',ERR=80) 3.14
80 CONTINUE
END
我是这样编译的:
gfortran -O0 -g -fcheck=all -o writesegfault2 writesegfault2.f
这是 Trusty 中的输出:
(trusty64)$ ./writesegfault2
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7F1B871EA777
#1 0x7F1B871EAD7E
#2 0x7F1B86E42D3F
#3 0x7F1B86EA41B4
#4 0x7F1B872A1D1E
#5 0x7F1B872AC43C
#6 0x7F1B872AE558
#7 0x40088E in writesegf2 at writesegfault2.f:4
Segmentation fault (core dumped)
GDB 说:
(trusty64)$ gdb ./writesegfault2
Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:153
153 ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory.
正如预期的那样,在 Precise 中根本没有输出:
(precise64)$ ./writesegfault2
(precise64)$
带有 ERR 标签的单个 WRITE 似乎可以正常工作,即使在 Trusty 中也是如此:
PROGRAM WRITEOK
WRITE (*,'(I8)',ERR=40) 3.14
40 CONTINUE
WRITE (*,'(I8)') 3
WRITE (*,'(E8.3)') 3.14
END
(trusty64)$ ./writeok
3
.314E+01
这是另一个变体:
PROGRAM WRITESEGF
WRITE (*,'(I8)',ERR=40) 3.14
40 CONTINUE
WRITE (*,'(I8)') 3.14
END
另一个分段错误似乎是由带有 ERR 标签的 WRITE 引起的,然后是一个简单的转换(应该是错误):
(trusty64)$ ./writesegfault
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7FF7F2BCB777
#1 0x7FF7F2BCBD7E
#2 0x7FF7F2823D3F
#3 0x7FF7F28851B4
#4 0x7FF7F2C82D1E
#5 0x7FF7F2C8D43C
#6 0x7FF7F2C8F558
#7 0x40088E in MAIN__ at writesegfault.f:4
Segmentation fault (core dumped)
不使用标签,应该是报错:
PROGRAM WRITEERR
WRITE (*,'(I8)') 3.14
END
运行时,在 Trusty 和 Precise 中:
(trusty64)$ ./writeerror
At line 2 of file writeerror.f (unit = 6, file = 'stdout')
Fortran runtime error: Expected INTEGER for item 1 in formatted transfer, got REAL
(I8)
^
我已经用不同版本的 gfortran 复制了所有这些:Precise 中的 4.6.3 和 Trusty 中的 4.8.4,我还切换了它们(在 Precise 中向后移植 4.8,在 Trusty 中安装 4.6),更改架构(32 位和 64 位),移动二进制文件。问题是一样的,所以我认为是 libgfortran 或 glib 的问题...
问题 1):为什么会有这些分段错误,为什么只在 Trusty 中?这可能是 glibc 中的回归吗?
问题 2):gfortran 中是否有一个标志实际上允许在最后一种情况下将 REAL 转换为 INTEGER?
【问题讨论】:
-
你的机器上安装了哪些版本的
gfortran? -
已通过 64 位 Trusty 确认,
GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4。而且我似乎也成功地用段错误杀死了gdb。这对我来说是第一次。 -
@AlexanderVogt 我已经编辑了问题以显示编译器版本和其他测试,我认为 gfortran 不是这里的问题,因为即使切换二进制文件也会导致段错误仅在 Trusty...
-
在 GNU Fortran (Ubuntu 5.2.1-23ubuntu1~15.10) 5.2.1 中不会出现
标签: segmentation-fault fortran gfortran