【问题标题】:Why does the following Fortran code allocate on the stack/heap depending on the contents of a derived type?为什么以下 Fortran 代码根据派生类型的内容在堆栈/堆上分配?
【发布时间】:2013-02-27 09:05:10
【问题描述】:

我不明白为什么如果bar 字段存在于containerType 中,则以下程序会出现SIGSEGV 段错误,并且如果将其注释掉则可以正常工作。我在 x86_64 上,同时使用 gfortran-4.4.6 和 gfortran-4.6.3 进行编译。

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

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

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

当我注释掉 bar 字段时,valgrind 非常高兴。更奇怪的是,在 gfortran-4.6.3 下使用 '-O' 编译也会使问题消失(但不是在 gfortran-4.4.6 下)。

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


有问题的代码:

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

【问题讨论】:

    标签: memory-management fortran gfortran


    【解决方案1】:

    这一定是 gfortran 中的一个错误。我看不出有什么问题。它也适用于 Intel 和 Oracle 编译器。最好将其报告给 gfortran 开发人员。我只使用了 2 天前的 gfortran 4.8 主干构建进行了尝试。

    该错误与堆栈/堆差异无关。它只是在allocate 语句期间崩溃。它甚至不适用于 stat=errmsg= 设置。

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

    【讨论】:

    • 我将可能的问题报告为gcc.gnu.org/bugzilla/show_bug.cgi?id=56471
    • 感谢您验证这是一个错误,拯救我的理智,并提交错误报告 - 我不知道正确的渠道,所以非常感谢。我现在将解决这个错误(通过在这里和那里引入几个指针)。
    猜你喜欢
    • 2015-11-04
    • 2012-11-27
    • 2019-12-07
    • 2015-10-15
    • 2011-02-18
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多