【问题标题】:gfortran WRITE err option causing segfaultgfortran WRITE err 选项导致段错误
【发布时间】: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


【解决方案1】:

看起来这确实是一个影响某些 Ubuntu 版本的错误,在 GCC bugzilla 中打开票证后,他们重现了该问题并追踪了修复:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68594

此问题影响 gfortran 4.8,部分影响 gfortran 4.9,应该在 gfortran 5.0 中修复。

我没有找到任何方法允许使用 gfortran 选项在 WRITE() 中将 REAL 转换为 INTEGER。

【讨论】:

    猜你喜欢
    • 2015-10-30
    • 2015-09-03
    • 2012-08-17
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多