# What is wrong with this code?

**URL:** <https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151>\
**Category:** Help\
**Created:** [August 10, 2022, 8:08pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151 "2022-08-10T20:08:45Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![nicholaswogan](https://avatars.discourse-cdn.com/v4/letter/n/f1d935/32.png) [@nicholaswogan](https://fortran-lang.discourse.group/u/nicholaswogan)\
**Post date:** [August 10, 2022, 8:08pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/1 "2022-08-10T20:08:45Z")

</div>

This code doesn’t work and I think it should

```fortran
program main
  use iso_fortran_env, only: dp => real64
  implicit none
  call test_fun1()

contains

  function fun1(a, err) result(b)
    real(dp), intent(in) :: a
    character(:), allocatable, intent(out) :: err
    real(dp) :: b(2)

    if (a > 2) then
      err = "a bigger than 2"
      return
    endif

    b = 1
  end function

  subroutine test_fun1()
    real(dp) :: a, b(2)
    character(:), allocatable :: err
    a = 3
    b = fun1(a, err)
    if (allocated(err)) then
      print*,'err is allocated'
      print*,'next line tries to print err'
      print*,err
    else
      print*,b
    endif
  end subroutine

end program

```

I compile and run with

```nohighlight
gfortran main.f90
./a.out

```

the result is

```nohighlight
(base) nicholas@Nicholass-MacBook-Air test_gfortran_err % ./a.out          
 err is allocated
 next line tries to print err

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0 0x102fb61c7
#1 0x102fb51a3
#2 0x194092c43
#3 0x1030ac65b
zsh: segmentation fault ./a.out

```

My compiler version is `GNU Fortran (Homebrew GCC 12.1.0) 12.1.0` and machine is a Macbook Air M1.

The problem somehow stems from `fun1` having an output that is an array. The same code, except if `b` is a just a scalar instead of an array, works just fine.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [August 10, 2022, 8:45pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/2 "2022-08-10T20:45:05Z")

</div>

> [@nicholaswogan](#):
>
> My compiler version is `GNU Fortran (Homebrew GCC 12.1.0) 12.1`

At first glance, this looks like a compiler issue. Other than deviating from the view of striving toward “pure” functions and thus no `INTENT(OUT)` or `INTENT(INOUT)` parameters, the code looks alright.

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [August 10, 2022, 8:46pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/3 "2022-08-10T20:46:54Z")

</div>

It works with Intel ifx 2022.1.0, under Ubuntu 22.04:

```auto
 err is allocated
 next line tries to print err
 a bigger than 2

```

But with GFortran 11.2.0, err is not printed (or is empty):

```auto
 err is allocated
 next line tries to print err
 

```

But no segfault.

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [August 10, 2022, 9:17pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/5 "2022-08-10T21:17:54Z")

</div>

> [@vmagnin](#):
>
> But no segfault.

In fact, when running several times the GFortran executable, sometimes no segfault, sometimes this message:

```auto
Memory allocation failure in xrealloc

```

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [August 10, 2022, 9:28pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/6 "2022-08-10T21:28:50Z")

</div>

> [@nicholaswogan](#):
>
> ```auto
> real(dp) :: b(2)
> 
> if (a > 2) then
> err = "a bigger than 2"
> return
> endif
> 
> b = 1
> 
> ```

Separately, the function result is not defined in the case where the received argument `a` is greater than 2. The standard requires a conforming program to define the function result and note the onus is on the programmer here.

---

<div class="post-metadata">

**Author:** ![nicholaswogan](https://avatars.discourse-cdn.com/v4/letter/n/f1d935/32.png) [@nicholaswogan](https://fortran-lang.discourse.group/u/nicholaswogan)\
**Post date:** [August 10, 2022, 9:31pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/7 "2022-08-10T21:31:36Z")

</div>

I get the same result when `b` is always defined. e.g.

```auto
  function fun1(a, err) result(b)
    real(dp), intent(in) :: a
    character(:), allocatable, intent(out) :: err
    real(dp) :: b(2)

    b = 1

    if (a > 2) then
      err = "a bigger than 2"
      return
    endif

  end function

```

---

<div class="post-metadata">

**Author:** ![septc](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/septc/32/77_2.png) [@septc](https://fortran-lang.discourse.group/u/septc)\
**Post date:** [August 10, 2022, 9:36pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/8 "2022-08-10T21:36:40Z")

</div>

I’ve modified the code a bit, such that the result variable (`b`) and the intent(out)-variable (`err`) in `fun1()` are always defined, and also initialized `err` before calling `fun1()` optionally (the line marked by \*):

```auto
program main
  use iso_fortran_env, only: dp => real64
  implicit none
  call test_fun1()

contains

  function fun1(a, err) result(b)
    real(dp), intent(in) :: a
    character(:), allocatable, intent(out) :: err
    real(dp) :: b(2)

    if (a > 2) then
      b(:) = -1
      err = "a bigger than 2"
      return
    endif

    b(:) = 1
    err = "OK"
  end function

  subroutine test_fun1()
    real(dp) :: a, b(2)
    character(:), allocatable :: err

    !! err = "dummy" !! (*)

    a = 3
    b = fun1(a, err)

    if (allocated(err)) then
      print *, 'err is allocated'
      print *, 'next line tries to print err'
      print *, len(err), len_trim(err)
      print *, err
    endif

    print *, b
  end subroutine

end program

```

Then, if the line (\*) is commented out, using Gfortran12 + Ubuntu22,

```auto
$ gfortran test.f90 && ./a.out
 err is allocated
 next line tries to print err
           0 0
 
  -1.0000000000000000 -1.0000000000000000 

```

while if the line (\*) is uncommented,

```auto
 err is allocated
 next line tries to print err
           5 5
 a big
  -1.0000000000000000 -1.0000000000000000  

```

The result also changes on an old MacMini, or with `-fsanitize=address`. It seems like the length of `err` is “retained” before and after the call (so 5 chars are printed when “dummy” is set). If `err` is not defined before the call, some garbage value will be “retained”, so resulting an undefined behavior (-\> accessing invalid memory if the random value is large or negative)?

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [August 10, 2022, 9:37pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/9 "2022-08-10T21:37:25Z")

</div>

You specified ERR as INTENT(OUT) but only define ERR when A\>2

---

<div class="post-metadata">

**Author:** ![nicholaswogan](https://avatars.discourse-cdn.com/v4/letter/n/f1d935/32.png) [@nicholaswogan](https://fortran-lang.discourse.group/u/nicholaswogan)\
**Post date:** [August 10, 2022, 9:55pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/10 "2022-08-10T21:55:27Z")

</div>

> [@urbanjost](#):
>
> You specified ERR as INTENT(OUT) but only define ERR when A\>2

Nope. I only allocate error when `a > 2`. That is different than being undefined. This is an OK thing to do.

Also, as @septc points out, it doesn’t matter if `err` is always allocated or not in `fun1`. You get the same result (seg fault)

---

<div class="post-metadata">

**Author:** ![nicholaswogan](https://avatars.discourse-cdn.com/v4/letter/n/f1d935/32.png) [@nicholaswogan](https://fortran-lang.discourse.group/u/nicholaswogan)\
**Post date:** [August 10, 2022, 9:59pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/11 "2022-08-10T21:59:52Z")

</div>

I get the exact same behavior with your modified code.

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [August 10, 2022, 11:15pm UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/12 "2022-08-10T23:15:30Z")

</div>

Actually testing it the machine code temporary for err is not allocated and it is a bug; so as you suspected if in the calling procedure you allocate err and make it big enough to hold the message you do not get the segfault. So in TEST\_FUN1 right before calling FUN1 add “err=AAAAAAAAAAAAAAAAAAA” and you will see the length stays the same and only part of the value gets replaced; or do not do that and after testing if ERR is allocated query the length with LEN(ERR) and you will get garbage. Since any INTENT(OUT) gets deallocated I agree ERR does not have to get set although I would personally never do that; but I also really avoid leaving anything  
unallocated like that so it looked “wrong” to me, I cannot think of a reason it is not standard conforming, and although ERR gets flagged as allocated I see no where where it ever allocates it, and cannot think of a reason that is not a bug.

---

<div class="post-metadata">

**Author:** ![Abhilash](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/abhilash/32/1635_2.png) [@Abhilash](https://fortran-lang.discourse.group/u/Abhilash)\
**Post date:** [August 11, 2022, 12:10am UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/13 "2022-08-11T00:10:31Z")

</div>

This is a very interesting discussion! I tried a couple of different variations of the original code that do not seem to encounter the bug. One variation replaces the function with a subroutine, while the other one packs `b` and `err` into a derived type which allows one to declare the function pure.

> **Code**
>
> ```auto
> program main
> use iso_fortran_env, only: dp => real64
> implicit none
> 
> type :: t1
> real(dp):: b(2)
> character(:), allocatable :: err
> endtype t1
> 
> call test_fun1()
> 
> contains
> 
> pure function fun1(a) result(t)
> real(dp), intent(in) :: a
> type(t1):: t
> 
> t%b = 1
> if (a > 2) then
> t%err = "a bigger than 2"
> return
> endif
> 
> end function
> 
> subroutine sub1(a,b,err)
> real(dp), intent(in) :: a
> real(dp), intent(out) :: b(2)
> character(:), allocatable,intent(out) :: err
> 
> b = 1
> if (a > 2) then
> err = "a bigger than 2"
> return
> endif
> 
> end subroutine
> 
> subroutine test_fun1()
> real(dp) :: a,b(2)
> type(t1) :: t
> character(:), allocatable :: err
> a = 3
> t = fun1(a)
> if (allocated(t%err)) then
> print*,'err is allocated'
> print*,'next line tries to print err'
> print*,t%err
> else
> print*,t%b
> endif
> 
> a = 1
> t = fun1(a)
> if (allocated(t%err)) then
> print*,'err is allocated'
> print*,'next line tries to print err'
> print*,t%err
> else
> print*,t%b
> endif
> 
> a = 3
> call sub1(a,b, err)
> if (allocated(err)) then
> print*,'err is allocated'
> print*,'next line tries to print err'
> print*,err
> else
> print*,b
> endif
> 
> a = 1
> call sub1(a,b, err)
> if (allocated(err)) then
> print*,'err is allocated'
> print*,'next line tries to print err'
> print*,err
> else
> print*,b
> endif
> 
> end subroutine
> 
> end program
> 
> ```

---

<div class="post-metadata">

**Author:** ![CRquantum](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/crquantum/32/730_2.png) [@CRquantum](https://fortran-lang.discourse.group/u/CRquantum)\
**Post date:** [August 11, 2022, 12:11am UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/14 "2022-08-11T00:11:29Z")

</div>

> [@nicholaswogan](#):
>
> `character(:), allocatable :: err`

Intel Fortran has no problem.  
Gfortran has problem.  
The cygwin64 gfortran on windows cannot show complete string, it shows things like ''a is bigge".  
Gfortran 11.2.0 on ubuntu has the same issue OP mentioned.

I don’t know why, but if you define

```auto
character(:), allocatable :: str   

```

inside a type as below,

```auto
  type :: var_char 
    character(:), allocatable :: str   
  end type var_char  

```

Then the code work with gfortran without problem.  
see below code, the !!! are the small modifications.

```auto
program main
  use iso_fortran_env, only: dp => real64
  implicit none
  
  type :: var_char !!!!!!!!!!!!!!!
    character(:), allocatable :: str !!!!!!!!!!!!!!!!!!!1 
  end type var_char !!!!!!!!!!!!!!!
  
  
  call test_fun1()

contains

  function fun1(a, err) result(b)
    real(dp), intent(in) :: a
    type(var_char) :: err !!!!!!!!!!!!!!!!!
    real(dp) :: b(2)
    if (a > 2) then
      err%str = 'a is bigger than 2' !!!!!!!!!!!!!!!!!!!!!
      return
    endif

    b = 1
  end function

  subroutine test_fun1()
    real(dp) :: a, b(2)
    type(var_char) :: err !!!!!!!!!!!!!!!!!!!!!
    
    a = 3
    b = fun1(a, err)
    if (allocated(err%str)) then !!!!!!!!!!!!!
      print*,'err is allocated'
      print*,'next line tries to print err'
      write(6,'(a)') err%str !!!!!!!!!!!!!!!!!
    else
      print*,b
    endif
  end subroutine

end program

```

See a similar topic,

> [@How to create a character array whose each element is just the right length based on its content?](https://fortran-lang.discourse.group/t/how-to-create-a-character-array-whose-each-element-is-just-the-right-length-based-on-its-content/2166):
>
> Dear all, A quick question, I want an array, each element is character type. But I want the len of each element is just the right size based on its content, instead of a fixed length for all elements. Is there an easy way to achieve this? See the code below, program main character(len=:), allocatable :: string(slight_smile character(len=:), allocatable :: string\_scalar allocate(character(len=20) :: string\_scalar) allocate(string(5),mold=repeat('0', 20)) string(1) = '123456789' …

In short, I don’t know why, but if

```auto
character(:), allocatable :: str   

```

needs to be used, it is best to define it inside a type.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [August 11, 2022, 12:49am UTC](https://fortran-lang.discourse.group/t/what-is-wrong-with-this-code/4151/15 "2022-08-11T00:49:35Z")

</div>

> [@nicholaswogan](#):
>
> `b = fun1(a, err)`

There is kind of a technical error here. fun1() is not defined in this original version of the code. The result is declared as a real array of length 2, but its values are not set. It is technically illegal to assign those undefined values to the array `b(:)`. Usually a simple assignment causes no problems, it is only when those random bit patterns are used in arithmetic expressions that problems arise. But it is an error nonetheless.

However, the later modifications of the code eliminate that usually benign error, and the code still aborts, so that was not the cause of the seg fault.
