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

Reallocation on assignment for derived type array with deferred-length components

jwmwalrus
New Contributor I
3,967 Views

Hi.

The following code aids in illustrating the problem.

implicit none

type :: sentence
    character(:), allocatable :: lower, upper
end type

type :: list
    type(sentence), allocatable :: list(:)
end type

integer :: i, n = 7
type(list) :: a

character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

a%list = [sentence ::]

do i = 0, n
    if (MOD(i, 2) == 0) then
        a%list = [a%list, sentence(LOWER(:13+i), UPPER(:13-i))]
    else
        a%list = [a%list, sentence(LOWER(i+1:), UPPER(:i+1))]
    endif
enddo

do i = 1, SIZE(a%list)
    print *, i, ', lower=',a%list(i)%lower, ', upper=', a%list(i)%upper
enddo

end

From the code, it's clear that the a%list%lower component shouldn't have any uppercase characters, but I get the following with the ifort compiler:

$ ifort -g -O0 test.f90 && ./a.out
           1 , lower=abcdefghijklm, upper=ABCDEFGHIJKLM
           2 , lower=cdefghijklmnopqrstuvwxyzA, upper=AB
           3 , lower=abcdefghijklmno, upper=ABCDEFGHIJK
           4 , lower=ghijklmnopqrstuvwxyzABC, upper=ABCD
           5 , lower=abcdefghijklmnopq, upper=ABCDEFGHI
           6 , lower=klmnopqrstuvwxyzABCDE, upper=ABCDEF
           7 , lower=abcdefghijklmnopqrs, upper=ABCDEFG
           8 , lower=opqrstuvwxyzABCDEFG, upper=ABCDEFGH

Enabling the default optimizatiions mitigates the problem:

$ ifort test.f90 && ./a.out
           1 , lower=abcdefghijklm, upper=ABCDEFGHIJKLM
           2 , lower=cdefghijklmnopqrstuvwxyz, upper=AB
           3 , lower=abcdefghijklmno, upper=ABCDEFGHIJK
           4 , lower=ghijklmnopqrstuvwxyz, upper=ABCD
           5 , lower=abcdefghijklmnopq, upper=ABCDEFGHI
           6 , lower=klmnopqrstuvwxyz, upper=ABCDEF
           7 , lower=abcdefghijklmnopqrs, upper=ABCDEFG
           8 , lower=opqrstuvwxyzA, upper=ABCDEFGH

 

Using the ifx compiler with no default optimizations seems to match expected behavior, except for the last entry:

$ ifx -g -O0 test.f90 && ./a.out
           1 , lower=abcdefghijklm, upper=ABCDEFGHIJKLM
           2 , lower=cdefghijklmnopqrstuvwxyz, upper=AB
           3 , lower=abcdefghijklmno, upper=ABCDEFGHIJK
           4 , lower=ghijklmnopqrstuvwxyz, upper=ABCD
           5 , lower=abcdefghijklmnopq, upper=ABCDEFGHI
           6 , lower=klmnopqrstuvwxyz, upper=ABCDEF
           7 , lower=abcdefghijklmnopqrs, upper=ABCDEFG
           8 , lower=opqrstuvwxy, upper=ABCDEFGH

And the something similar happens for ifx with the default optimizations:

$ ifx test.f90 && ./a.out
           1 , lower=abcdefghijklm, upper=ABCDEFGHIJKLM
           2 , lower=cdefghijklmnopqrstuvwxyz, upper=AB
           3 , lower=abcdefghijklmno, upper=ABCDEFGHIJK
           4 , lower=ghijklmnopqrstuvwxyz, upper=ABCD
           5 , lower=abcdefghijklmnopq, upper=ABCDEFGHI
           6 , lower=klmnopqrstuvwxyz, upper=ABCDEF
           7 , lower=abcdefghijklmnopqrs, upper=ABCDEFG
           8 , lower=opqrstuvwxyzA, upper=ABCDEFGH

These are the compiler versions:

$ ifort -V && ifx -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2023.1.0 Build 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 

1 Solution
Barbara_P_Intel
Employee
1,662 Views

Please try the latest ifx and ifort versions that were released last week. Looks to me like it's working now.



View solution in original post

0 Kudos
31 Replies
andrew_4619
Honored Contributor III
2,777 Views

I tried your code on Windows with default optimisation and no optimisation and got some different spurious variants. I suspect the array constructor is at fault as there seem to have been a number of recent bugs on this.

ifort test_dt_alloc.f90 /Od
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.30.30709.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:test_dt_alloc.exe
-subsystem:console
test_dt_alloc.obj

test_dt_alloc
           1 , lower=abcdefghijklm, upper=ABCDEFGHIJKLM
           2 , lower=cdefghijklmnopqrstuvwxyzA, upper=AB
           3 , lower=abcdefghijklmno, upper=ABCDEFGHIJK
           4 , lower=ghijklmnopqrstuvwxyzABC, upper=ABCD
           5 , lower=abcdefghijklmnopq, upper=ABCDEFGHI
           6 , lower=klmnopqrstuvwxyzABCDE, upper=ABCDEF
           7 , lower=abcdefghijklmnopqrs, upper=ABCDEFG
           8 , lower=opqrstuvwxyzABCDEFG, upper=ABCDEFGH

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ifort test_dt_alloc.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.30.30709.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:test_dt_alloc.exe
-subsystem:console
test_dt_alloc.obj

test_dt_alloc
           1 , lower=abcdefghijklm, upper=ABCDEFGHIJKLM
           2 , lower=cdefghijklmnopqrstuvwxyz , upper=AB
           3 , lower=abcdefghijklmno, upper=ABCDEFGHIJK
           4 , lower=ghijklmnopqrstuvwxyz   , upper=ABCD
           5 , lower=abcdefghijklmnopq, upper=ABCDEFGHI
           6 , lower=klmnopqrstuvwxyz     , upper=ABCDEF
           7 , lower=abcdefghijklmnopqrs, upper=ABCDEFG
           8 , lower=opqrstuvwxyz      A, upper=ABCDEFGH

optimisation  

0 Kudos
andrew_4619
Honored Contributor III
2,772 Views

consider this program, which also gives interesting results! 

 

program test_dt_alloc2
implicit none

type :: sentence
    character(:), allocatable :: lower, upper
end type

integer :: i, n = 7
type(sentence) :: b

character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

do i = 0, n
    if (MOD(i, 2) == 0) then
        b = sentence(LOWER(:13+i), UPPER(:13-i))
    else
        b = sentence(LOWER(i+1:), UPPER(:i+1))
    endif
    print *, i, ', b%lower ',b%lower, ', b%upper= ', b%upper
enddo
end

 

ifort test_dt_alloc2.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.30.30709.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:test_dt_alloc2.exe
-subsystem:console
test_dt_alloc2.obj

test_dt_alloc2
           0 , b%lower abcdefghijklm, b%upper= ABCDEFGHIJKLM
           1 , b%lower cdefghijklmnopqrstuvwxyz , b%upper= AB
           2 , b%lower abcdefghijklmno, b%upper= ABCDEFGHIJK
           3 , b%lower ghijklmnopqrstuvwxyz   , b%upper= ABCD
           4 , b%lower abcdefghijklmnopq, b%upper= ABCDEFGHI
           5 , b%lower klmnopqrstuvwxyz     , b%upper= ABCDEF
           6 , b%lower abcdefghijklmnopqrs, b%upper= ABCDEFG
           7 , b%lower opqrstuvwxyz      A, b%upper= ABCDEFGH

 

 

 

andrew_4619
Honored Contributor III
2,768 Views

This one is well behaved. So the default constructor for sentence seem to be the problem....

 

program test_dt_alloc3
implicit none
integer :: i, n = 7

character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

do i = 0, n
    if (MOD(i, 2) == 0) then
        print *, i, ', b%lower ',LOWER(:13+i), ', b%upper= ', UPPER(:13-i)
    else
        print *, i, ', b%lower ',LOWER(i+1:), ', b%upper= ', UPPER(:i+1)
    endif
enddo
end

 

 

 

Barbara_P_Intel
Employee
2,764 Views

@jwmwalrus, Thanks for reporting this. I see the same thing with pre-production compilers

@andrew_4619, having more reproducers is great! Thank you.

I'll get a bug filed today.


0 Kudos
Barbara_P_Intel
Employee
2,738 Views

I filed CMPLRLLVM-49308 for you both. I will let you know when it's fixed.


0 Kudos
jwmwalrus
New Contributor I
2,579 Views

Hi.

It's funny how, by trying to simplify the test case as much as possible, I stumbled upon a different thing.

 

In the original code, the issue is with reallocation on assignment when the derived type has a deferred-length character component (and the workaround is to use MOVE_ALLOC).

The following code (which could be shortened further, I admit) illustrates the problem:

module tables
    implicit none
    private
    save

    type, public :: table_entry
        character(:), allocatable :: key
        character(:), allocatable :: val
    end type

    interface table_entry
        module procedure table_entry_new
    end interface

    type, public :: table
        type(table_entry), allocatable :: storage(:)
    contains
        procedure, private :: add_entry1
        generic :: add => add_entry1
    end type

contains
    function table_entry_new(i, k, v) result(new)
        type(table_entry) :: new
        integer, intent(in) :: i
        character(*), intent(in) :: k, v
        new%key = k
        new%val = v
    end function

    subroutine add_entry1(this, kv)
        class(table), intent(inout) :: this
        type(table_entry), intent(in) :: kv
        integer :: i

        print'(/a)','value to add:'
        print*,'key=',kv%key,', val=',kv%val

        print '(/a)','storage, before adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo

        this%storage = [this%storage, kv]

        print'(/a)','storage, after adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo
    end subroutine
end module tables

use tables

implicit none

integer :: i, n = 7
type(table) :: h
type(table_entry) :: kv
character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

h%storage = [table_entry :: ]

do i = 0, n
    if (MOD(i, 2) == 0) then
        kv = table_entry(i, LOWER(:13+i), UPPER(:13-i))
    else
        kv = table_entry(i, LOWER(i+1:), UPPER(:i+1))
    endif
    call h%add(kv)
enddo
end

Please notice that I'm using a custom constructor.

Here's the output:

$ ifort test.f90 && ./a.out 

value to add:
 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, before adding:

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

value to add:
 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, after adding:
           1 key=abcdefghijklm, val=��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

value to add:
 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, before adding:
           1 key=abcdefghijklm, val=��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, after adding:
           1 key=abcdefghijklm, val=0 �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

value to add:
 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, before adding:
           1 key=abcdefghijklm, val=0 �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=��
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

value to add:
 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=��
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

value to add:
 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

value to add:
 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

value to add:
 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=bcdefghijklmnopqrst, val=ABCDEFG
           8 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

In the original code, the table, when saved to a file, contains some caret notation symbols, so I guess this test is much closer.

 

And this is the output using gfortran:

$ gfortran test.f90 && ./a.out 

value to add:
 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, before adding:

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

value to add:
 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

value to add:
 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

value to add:
 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

value to add:
 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

value to add:
 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

value to add:
 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

value to add:
 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG
           8 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

 

0 Kudos
jwmwalrus
New Contributor I
2,579 Views

Hi.

It's funny how, by trying to simplify the test case as much as possible, I stumbled upon a different thing.

 

In the original code, the issue is with reallocation on assignment when the derived type has a deferred-length character component (and the workaround is to use MOVE_ALLOC).

The following code (which could be shortened further, I admit) illustrates the problem:

 

module tables
    implicit none
    private
    save

    type, public :: table_entry
        character(:), allocatable :: key
        character(:), allocatable :: val
    end type

    interface table_entry
        module procedure table_entry_new
    end interface

    type, public :: table
        type(table_entry), allocatable :: storage(:)
    contains
        procedure, private :: add_entry1
        generic :: add => add_entry1
    end type

contains
    function table_entry_new(i, k, v) result(new)
        type(table_entry) :: new
        integer, intent(in) :: i
        character(*), intent(in) :: k, v
        new%key = k
        new%val = v
    end function

    subroutine add_entry1(this, kv)
        class(table), intent(inout) :: this
        type(table_entry), intent(in) :: kv
        integer :: i

        print'(/a)','value to add:'
        print*,'key=',kv%key,', val=',kv%val

        print '(/a)','storage, before adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo

        this%storage = [this%storage, kv]

        print'(/a)','storage, after adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo
    end subroutine
end module tables

use tables

implicit none

integer :: i, n = 7
type(table) :: h
type(table_entry) :: kv
character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

h%storage = [table_entry :: ]

do i = 0, n
    if (MOD(i, 2) == 0) then
        kv = table_entry(i, LOWER(:13+i), UPPER(:13-i))
    else
        kv = table_entry(i, LOWER(i+1:), UPPER(:i+1))
    endif
    call h%add(kv)
enddo
end

 

Please notice that I'm using a custom constructor.

Here's the output:

 

$ ifort test.f90 && ./a.out 

value to add:
 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, before adding:

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

value to add:
 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, after adding:
           1 key=abcdefghijklm, val=��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

value to add:
 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, before adding:
           1 key=abcdefghijklm, val=��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, after adding:
           1 key=abcdefghijklm, val=0 �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

value to add:
 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, before adding:
           1 key=abcdefghijklm, val=0 �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=��
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

value to add:
 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=��
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

value to add:
 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

value to add:
 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

value to add:
 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=bcdefghijklmnopqrst, val=ABCDEFG
           8 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

 

In the original code, the table is saved to a file and contains some caret notation symbols, so I guess this test is much closer.

 

 

 

0 Kudos
jwmwalrus
New Contributor I
2,700 Views

Btw, it seems that editing a post in this forum, makes it disappear completely.

0 Kudos
jwmwalrus
New Contributor I
2,690 Views

(Reposted, since it got deleted.)

Hi.

It's funny how, by trying to simplify the test case as much as possible, I stumbled upon a different thing.

In the original code, the issue is with reallocation on assignment when the derived type has a deferred-length character component (and the workaround is to use MOVE_ALLOC).

The following code (which could be shortened further, I admit) illustrates the problem:

 

module tables
    implicit none
    private
    save

    type, public :: table_entry
        character(:), allocatable :: key
        character(:), allocatable :: val
    end type

    interface table_entry
        module procedure table_entry_new
    end interface

    type, public :: table
        type(table_entry), allocatable :: storage(:)
    contains
        procedure, private :: add_entry1
        generic :: add => add_entry1
    end type

contains
    function table_entry_new(i, k, v) result(new)
        type(table_entry) :: new
        integer, intent(in) :: i
        character(*), intent(in) :: k, v
        new%key = k
        new%val = v
    end function

    subroutine add_entry1(this, kv)
        class(table), intent(inout) :: this
        type(table_entry), intent(in) :: kv
        integer :: i

        print'(/a)','value to add:'
        print*,'key=',kv%key,', val=',kv%val

        print '(/a)','storage, before adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo

        this%storage = [this%storage, kv]

        print'(/a)','storage, after adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo
    end subroutine
end module tables

use tables

implicit none

integer :: i, n = 7
type(table) :: h
type(table_entry) :: kv
character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

h%storage = [table_entry :: ]

do i = 0, n
    if (MOD(i, 2) == 0) then
        kv = table_entry(i, LOWER(:13+i), UPPER(:13-i))
    else
        kv = table_entry(i, LOWER(i+1:), UPPER(:i+1))
    endif
    call h%add(kv)
enddo
end

 

Please notice that I'm using a custom constructor.

Here's the output:

 

$ ifort test.f90 && ./a.out 

value to add:
 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, before adding:

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

value to add:
 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, after adding:
           1 key=abcdefghijklm, val=��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

value to add:
 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, before adding:
           1 key=abcdefghijklm, val=��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, after adding:
           1 key=abcdefghijklm, val=0 �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

value to add:
 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, before adding:
           1 key=abcdefghijklm, val=0 �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=��
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

value to add:
 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=��
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

value to add:
 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

value to add:
 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

value to add:
 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key=��I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=bcdefghijklmnopqrst, val=ABCDEFG
           8 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

 

In the original code, the table is saved to a file and contains some caret notation symbols, so I guess this test is much closer.

 

0 Kudos
Barbara_P_Intel
Employee
2,629 Views

Thanks for another reproducer! I added it to the bug report.


0 Kudos
Ron_Green
Moderator
2,464 Views

@jwmwalrus we have a fix in the works for this one.  Look for it in 2024.0

0 Kudos
Barbara_P_Intel
Employee
2,038 Views

The reproducers are printing the correct results for both ifx and ifort with the compilers that were released earlier this week.

Please check out the new compiler versions!



0 Kudos
jwmwalrus
New Contributor I
2,003 Views

Hi.

Thanks for the follow-up.

I'm still getting similar behavior with the latest version of ifort/ifx:

This is the code (same as the one posted above):

module tables
    implicit none
    private
    save

    type, public :: table_entry
        character(:), allocatable :: key
        character(:), allocatable :: val
    end type

    interface table_entry
        module procedure table_entry_new
    end interface

    type, public :: table
        type(table_entry), allocatable :: storage(:)
    contains
        procedure, private :: add_entry1
        generic :: add => add_entry1
    end type

contains
    function table_entry_new(i, k, v) result(new)
        type(table_entry) :: new
        integer, intent(in) :: i
        character(*), intent(in) :: k, v
        new%key = k
        new%val = v
    end function

    subroutine add_entry1(this, kv)
        class(table), intent(inout) :: this
        type(table_entry), intent(in) :: kv
        integer :: i

        print'(/a)','value to add:'
        print*,'key=',kv%key,', val=',kv%val

        print '(/a)','storage, before adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo

        this%storage = [this%storage, kv]

        print'(/a)','storage, after adding:'
        do i = 1, SIZE(this%storage)
            print *,i,'key=',this%storage(i)%key,', val=',this%storage(i)%val
        enddo
    end subroutine
end module tables

use tables

implicit none

integer :: i, n = 7
type(table) :: h
type(table_entry) :: kv
character(*), parameter :: LOWER = 'abcdefghijklmnopqrstuvwxyz'
character(*), parameter :: UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

h%storage = [table_entry :: ]

do i = 0, n
    if (MOD(i, 2) == 0) then
        kv = table_entry(i, LOWER(:13+i), UPPER(:13-i))
    else
        kv = table_entry(i, LOWER(i+1:), UPPER(:i+1))
    endif
    call h%add(kv)
enddo
end

And this is the output I get:

(ins)$ ifx -V test.f90 && ./a.out
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.0.0 Build 20231017
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 Intel(R) Fortran 24.0-1238.2
GNU ld (GNU Binutils for Debian) 2.41

value to add:
 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, before adding:

storage, after adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

value to add:
 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, before adding:
           1 key=abcdefghijklm, val=ABCDEFGHIJKLM

storage, after adding:
           1 key=abcdefghijklm, val= �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

value to add:
 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, before adding:
           1 key=abcdefghijklm, val= �I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB

storage, after adding:
           1 key=abcdefghijklm, val=0��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

value to add:
 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, before adding:
           1 key=abcdefghijklm, val=0��I
           2 key=bcdefghijklmnopqrstuvwxyz, val=AB
           3 key=abcdefghijklmno, val=ABCDEFGHIJK

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val= �
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

value to add:
 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val= �
           3 key=abcdefghijklmno, val=ABCDEFGHIJK
           4 key=defghijklmnopqrstuvwxyz, val=ABCD

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

value to add:
 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=abcdefghijklmnopq, val=ABCDEFGHI

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

value to add:
 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=fghijklmnopqrstuvwxyz, val=ABCDEF

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

value to add:
 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

storage, before adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=abcdefghijklmnopqrs, val=ABCDEFG

storage, after adding:
           1 key=abcdefghijklm, val=abcdefghijklm
           2 key=bcdefghijklmnopqrstuvwxyz, val=ab
           3 key= �I, val=ABCDEFGHIJK
           4 key=bcdefghijklmnopqrstuvwx, val=ABCD
           5 key=bcdefghijklmnopqr, val=ABCDEFGHI
           6 key=bcdefghijklmnopqrstuv, val=ABCDEF
           7 key=bcdefghijklmnopqrst, val=ABCDEFG
           8 key=hijklmnopqrstuvwxyz, val=ABCDEFGH

 

 

 

0 Kudos
Barbara_P_Intel
Employee
1,955 Views

Well, heck! I tried it before I posted the news and I thought printed correctly. But it doesn't.

I'll let the compiler person know.



0 Kudos
Barbara_P_Intel
Employee
1,686 Views

@jwmwalrus, the two cases you posted actually two different bugs according to the compiler engineer. Both will be fixed in 2024.1.0 due to be available in a few months.

 

 

0 Kudos
Adelson_BR
Novice
1,885 Views

I have a similar problem that seems to point to a different origin of this bug.

 

Suppose that in the original code by @jwmwalrus one redefines the type sentence:

 

type :: sentence

    character(:), allocatable :: lower, upper

end type

 

to a new one like that:

 

type :: sentence

    real, allocatable :: A(:)

  ! real, pointer :: A(:)

end type 

 

Note the option to declare the component A as a pointer.

 

In my code, the component A is corrupted after reallocation of a%list if A is allocatable. But A is NOT corrupted after reallocation of a%list if A is a pointer that is allocated before it.

 

Thus, I believe this bug is not triggered by reallocation only. 

Hope this reply helps.

I can post a snippet code if necessary.

 

 

 

0 Kudos
Barbara_P_Intel
Employee
1,781 Views

@Adelson_BR, a complete reproducer would be useful! The compiler team likes to confirm fixes against multiple examples.

0 Kudos
Adelson_BR
Novice
1,699 Views

Hi, Barbara_P_Intel,

Sorry for the delay.

The folowing code reproduces the bug and also shows that using pointers prevents the bug. 

The idea is to work with a structure (C) that contains another struture (C(#)%B) that in turn contains matrices A (C(#)%B(#)%A). Reallocations of C and C(#)%B are made in a subroutine but one could reproduce the bug in a DO loop as @jwmwalrus  did. Like the problem reported by @jwmwalrus, the content of matrix A is corrupted when C(#)%B is reallocated.

The code is in the attached file teste_realoca_tipos.f90.

I've tried ifx and ifort 2023. I also tried gfortran. Gfortran does not even compile for versions up to 12 but Gfortran works fine for versions 13+. 

0 Kudos
Adelson_BR
Novice
1,699 Views

@Barbara_P_Intel ,

 

I did not test this with ifort 2024 yet.

 

Thanks a lot.

0 Kudos
Barbara_P_Intel
Employee
1,687 Views

@Adelson_BR, what output do you expect from your code?

I also tried commenting out the ALLOCATABLE and using POINTER. I got a runtime seg fault.

 

0 Kudos
Reply