为什么以下Fortran代码在堆栈/堆上分配取决于派生类型的内容? [英] Why does the following Fortran code allocate on the stack/heap depending on the contents of a derived type?

查看:236
本文介绍了为什么以下Fortran代码在堆栈/堆上分配取决于派生类型的内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么如果在 containerType 中存在 bar 字段,为什么以下程序会使用SIGSEGV进行段错误,并且如果它被注释掉就毫无问题地工作。我使用的是x86_64,使用gfortran-4.4.6和gfortran-4.6.3进行编译。

据我所知,使用指向 containerType 的指针应该强制分配包含的大数组堆,但似乎并非如此。在可执行文件上运行 valgrind 给我

 警告:客户端切换堆栈? SP更改:0x7ff000448  - > 0x7fe0603f8 
压制,使用:--max-stackframe = 16384080或更大

其余的输出是恕我直言不相关,但如果需要我可以编辑它)。这表明存在堆栈溢出;大概是由于在堆栈中分配了8 * 8 * 8 * 4000 * 8(字节/实际)= 16384000字节。



当我注释掉 bar 字段, valgrind 非常高兴。为了让甚至变得更为重要,在gfortran-4.6.3下使用'-O'编译也会导致问题消失(但不在gfortran-4.4.6下)。



要么我偶然发现了一个编译器错误,或者(更可能是因为我对Fortran相当陌生),我不明白数据的分配位置。有人能告诉我发生了什么事吗?






有问题的代码:

main.f90:

 程序主体

使用problematicArray
隐含无
类型(containerType),指针::容器
分配(容器)

容器%foo%arrayData = 17.0
写(*,*)容器%foo% arrayData(7,7,7,100)
deallocate(容器)
写入(*,*)'程序完成'

结束程序main

problematicArray.f90:

  module problematicArray 
隐式无
私有

整数,参数,public :: dim1 = 4000

类型,public :: typeWith4DArray
real(8 ),dimension(8,8,8,dim1):: arrayData
结束类型typeWith4DArray

类型:: typeWithChars
字符(4),dimension(:),allocatable: :charData
结束类型typeWithChars

type,public :: containerType
type(typeWith4DArray):: foo
type(typeWithChars):: bar
结束类型containerType

结束模块problematicArray


解决方案

这肯定是gfortran中的一个bug。我没有看到任何错误。它也适用于英特尔和Oracle编译器。最好向gfortran开发者汇报。我试了一下,只用了2天的 gfortran 4.8 trunk。



这个错误没有任何关系与堆栈/堆的区别。它只是在分配语句期间崩溃。它甚至不适用于 stat = errmsg = set。



请注意,您可以将模块和主程序放在单个源文件中。


I do not understand why the following program segfaults with a SIGSEGV if the bar field is present in containerType, and works without problems if it is commented out. I'm on x86_64, compiling with both gfortran-4.4.6 and gfortran-4.6.3.

As I understand it, using a pointer to containerType should force the allocation of the contained big array to happen on the heap but that doesn't seem to be the case. Running valgrind on the executable gives me

Warning: client switching stacks?  SP change: 0x7ff000448 --> 0x7fe0603f8
         to suppress, use: --max-stackframe=16384080 or greater

(The rest of the output is IMHO not relevant, but I could edit it in if required). This indicates to me that there's a stack overflow; presumably due to allocating the 8*8*8*4000 * 8(bytes per real) = 16384000 bytes on the stack.

When I comment out the bar field, valgrind is perfectly happy. To make matters even stranger, compiling under gfortran-4.6.3 with '-O' also makes the problem go away (but not under gfortran-4.4.6).

Either I've stumbled on a compiler bug, or (more likely, as I'm pretty new to Fortran) I don't understand where data is allocated. Could someone enlighten me what's going on?


The code in question:

main.f90:

program main 

    use problematicArray
    implicit none    
    type (containerType),pointer :: container
    allocate(container)

    container%foo%arrayData = 17.0
    write(*,*) container%foo%arrayData(7,7,7,100)
    deallocate(container)
    write(*,*) 'Program finished'

end program main

problematicArray.f90:

module problematicArray
    implicit none
    private

    integer, parameter, public :: dim1 = 4000 

    type, public :: typeWith4DArray
        real(8), dimension(8,8,8,dim1) ::  arrayData 
    end type typeWith4DArray

    type :: typeWithChars
        character(4), dimension(:), allocatable :: charData
    end type typeWithChars

    type, public :: containerType
        type(typeWith4DArray) :: foo
        type(typeWithChars) :: bar
    end type containerType

end module problematicArray

解决方案

This must be a bug in gfortran. I do not see anything wrong there. It also works in Intel and Oracle compilers. Best to report it to gfortran developers. I tried it with only a 2 days old build of the gfortran 4.8 trunk.

The error has nothing to do with stack/heap difference. It simply crashes during the allocate statement. It does not even work with stat= and errmsg= set.

Just a note, you can have the module and the main program inside a single source file.

这篇关于为什么以下Fortran代码在堆栈/堆上分配取决于派生类型的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆