【问题标题】:Fortran thinks non allocated array is already allocatedFortran 认为未分配的数组已经分配
【发布时间】:2018-09-01 00:29:23
【问题描述】:

我面临以下问题,无法弄清楚发生了什么。

我有一个例程在我的代码开头分配一些工作数组。这些工作数组是数据结构的一部分。

结构定义为:

 Type bond_stat
  Real*8,Allocatable,Dimension( : , : ) ::data_space
  Real*8,Allocatable,Dimension( : , : ) ::data_time
  Real*8,Allocatable,Dimension( : )     ::bin_width         
  Real*8,Allocatable,Dimension( : )     ::time
  Integer,Allocatable,Dimension( : , : )  ::connection_table
 End Type bond_stat
 Type( bond_stat ),allocatable,dimension( : ) ::Hbonds

这是在模块内完成的。我正在做的下一步是将这个结构分配为

Allocate( Hbonds( 1:2 ) )

然后我调用一个子例程,在该子例程中分配结构中包含的数组。奇怪的是现在如果我尝试用

分配数组
 Allocate( Hbonds( i )%data_space( 1 : 3 , 1 : Nbins ) )
 Allocate( Hbonds( i )%data_time( 1 : 1 , 1 : Nbins ) )
 Allocate( Hbonds( i )%time( 1 : N ) )
 Allocate( Hbonds( i )%bin_width( 1 : 2 ) )
 Allocate( Hbonds( i )%connection_table( 1 : 2 , 1 : N ) ) )

如果我这样做,代码会在执行时说明时间数组已经分配。我 100% 确定我以前没有分配过这个数组。我也确定该数组以前没有使用过,也许编译器会分配它,因为它已经在使用中。 所以我想我会检查数组是否已分配,如果已分配,则解除分配并重新分配。 如果这样做,我会在释放行中收到分段错误:

    If ( Allocated( Hbonds( i )%time ) ) then
       Deallocate( Hbonds( i )%time )
    End If
    Allocate( Hbonds( i )%time( 1 : N ) )

我完全不明白这里发生了什么。请任何人都可以帮忙。 输出如下:

Program received signal SIGSEGV: Segmentation fault - invalid memory 
reference.
Backtrace for this error:
#0  0x2b54685d3f0d in ???
#1  0x2b54685d314d in ???
#2  0x2b5468e4acaf in ???
#3  0x2b5468e9715c in ???
#4  0x4d27cf in __bond_statistics_MOD_bond_stat_init
at/fs/home/jona/programs/gfortran/eval_new01/playground/H_bond_analysis.f90:35
#5  0x4c8f5f in __bond_statistics_MOD_prep_bond_stat
at/fs/home/jona/programs/gfortran/eval_new01/playground/H_bond_analysis.f90:
350
#6  0x44477a in ???
#7  0x446724 in ???
#8  0x2b5468e35f44 in ???
#9  0x4016c8 in ???
#10  0xffffffffffffffff in ???
Segmentation fault (core dumped)

当不尝试在数组看起来像之前解除分配时:

At line 38 of file H_bond_analysis.f90
Fortran runtime error: Attempting to allocate already allocated variable 'hbonds'
Error termination. Backtrace:
#0  0x2ae8991bef0d in ???
#1  0x2ae8991bfa45 in ???
#2  0x2ae8991bfdfa in ???
#3  0x4d28e5 in __bond_statistics_MOD_bond_stat_init
at/fs/home/jona/programs/gfortran/eval_new01/playground/H_bond_analysis.f90:38
#4  0x4c8f5f in __bond_statistics_MOD_prep_bond_stat
at/fs/home/jona/programs/gfortran/eval_new01/playground/H_bond_analysis.f90:350
#5  0x44477a in ???
#6  0x446724 in ???
#7  0x2ae899a20f44 in ???
#8  0x4016c8 in ???
#9  0xffffffffffffffff in ???

第 38 行是分配时间的行。我正在使用带有标志的 gfortran 编译器 FLAGS = -fopenmp -g -Wall -fcheck=all -fbounds-check

【问题讨论】:

  • Nbins 是什么?
  • 如果显示已分配,则打印出size() 以查看分配给了什么。
  • 将每一段代码(i = 1,nbins = 10,N = 5)放在一个程序中不会引发 gfortran 错误。问题可能出在调用您的子例程的方式上。你能定义你写的每一段代码的范围吗?比如“这个属于一个模块”、“这个被那个调用”等等。
  • 请不要说“它说”,将实际输出复制并粘贴到问题中,包括行号等。完整的错误信息。此外,此类错误可能是由某些内存损坏引起的。我什至认为很有可能。因此,您绝对必须准备minimal reproducible example,因为错误很容易出现在您未显示的某些代码中。
  • 不要忘记启用 gfortran 的所有调试选项-g -Wall -fcheck=all。然后尝试消毒而不是-g -fsanitize=address,undefined。然后尝试valgrind。但是minimal reproducible example绝对必要

标签: segmentation-fault fortran gfortran dynamic-allocation


【解决方案1】:

我现在知道问题出在哪里了。我正在使用 makefile 来编译代码。今天我想在 bond_stat 模块中添加更多的数组,在执行 makefile 后我又遇到了同样的错误。我现在所做的是手动重新编译所有模块,而不更改代码本身的任何内容。这样就解决了问题。

【讨论】:

  • 所以看起来Makefile中的依赖关系有一个错误,即当模块重新编译时,并非所有use模块的文件都被重新编译。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 2019-12-27
  • 2020-03-17
  • 1970-01-01
相关资源
最近更新 更多