Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29389 Discussions

How to allocate memory for an array of derived type, which also contains allocatable array?

woshiwuxin
Novice
1,296 Views
Hi, everyone! I think this might be a general question.

Suppose we've defined a derived data type which includes an allocatable array.

[fortran]  type textline
    character(len=2)::atom_label
    integer(kind=4)::atom
    real(kind=8),dimension(:),allocatable::coord
  end type textline
[/fortran]

Then we also define an allocatable array of this derived type.

[fortran]  type(textline),dimension(:),allocatable::datum
[/fortran]

Now the question is how to allocate memory for datum?

I've tried the following.

[fortran]  integer(kind=4)::m,n,info
  m=10
  n=3
  allocate(datum(m)%coord(n),stat=info)
  if (info/=0) stop "Error."
[/fortran]

ifort reports no error, however, there's a segment fault in run-time.

Does anyone have any experience on this issue?

Thank you in advance!

0 Kudos
1 Solution
Tim_Gallagher
New Contributor II
1,296 Views

Do it in two different steps:

[bash]ALLOCATE(datnum(m))
DO I = 1, m
  ALLOCATE(datnum(I)%coord(n))
END DO[/bash]

Think of it this way: datnum has to exist before the %coord part exists. So you create m datnums, then you create n coords inside each of the m datnums.

The segfault is because you are trying to access datnum%coord before any datnum's exist.

Tim

View solution in original post

0 Kudos
4 Replies
Tim_Gallagher
New Contributor II
1,297 Views

Do it in two different steps:

[bash]ALLOCATE(datnum(m))
DO I = 1, m
  ALLOCATE(datnum(I)%coord(n))
END DO[/bash]

Think of it this way: datnum has to exist before the %coord part exists. So you create m datnums, then you create n coords inside each of the m datnums.

The segfault is because you are trying to access datnum%coord before any datnum's exist.

Tim

0 Kudos
woshiwuxin
Novice
1,296 Views

Thank you!

I've tried your approach, it works!

Actually, I've also tried this way.

[fortran]allocate(datum(m))
allocate(datum(m)%coord(n))[/fortran]
However, it doesn't work. The %coord part is still not assigned in memory. Maybe the do loop is the only way to the problem.

0 Kudos
Tim_Gallagher
New Contributor II
1,296 Views

What you posted there would work because after the first allocate on datum, there are m datum's.

The second allocate only allocates coord in the m-th datum. datum(1) to datum(m-1) still have not had their coord array allocated. The segfault happens when you try to access datum(1)%coord.

To do what you are trying to do, it would be allocate(datum(:)%coord(n)) for the second line. You can try this, but it won't work!

You can't pass only the components of the full array of derived types. In other words, the range specifier (ie. min:max where min and max are optional) has to appear after the last %. Meaning:

[fortran]TYPE myType1
 REAL, DIMENSION(m) :: data
END TYPE

TYPE myType2
 TYPE(myType1), DIMENSION(n) :: mt2
END TYPE

TYPE(myType2), DIMENSION(o) :: mt

CALL MySub(mt(:)%mt2(I)%data(:)) ! Wrong
CALL MySub(mt(I)%mt2(:)%data(:)) ! Wrong
CALL MySub(mt(I)%mt2(J)%data(:)) ! Right[/fortran]
Tim

0 Kudos
woshiwuxin
Novice
1,296 Views
Thanks, Tim! I've tried. It doesn't work.

To do what you are trying to do, it would be allocate(datum(:)%coord(n)) for the second line. You can try this, but it won't work!

0 Kudos
Reply