1 (edited by davidb 2016-01-30 10:26:36)

Topic: Debugging OOP

I am getting back into OOP but in Fortran 2003. I have the following code, which solves a non-linear equation f(x) = x^2 - 1
using bisection on an initial interval 0 to 2 (the correct result is 1 of course).

I am using a type data_t to setup the various constants needed by the function being solved. This is derived from the abstract class bundle_t (which has no components). The solve subroutine passes values of x (trial solutions) and the bundle variable (which happens to have the dynamic type of data_t) to the function. Bisection is used to get the solution.

I am doing it this was so I can solve any function by providing the correct f and a suitable extended type. At the moment everything is in 1 file. But eventually I will separate the "utility" module from the "user problem" module in separate files.

I am quite sure the code is correct and it does work.

However, I cannot trace execution through the solve function using the debugger. The code just freezes when I step into it, and it won't step again or continue. Any ideas?

module solver

   ! Abstract type, problem data type is an extension of this.
   type, abstract :: bundle_t
   end type bundle_t
   
contains

   function solve(f, a, b, bundle)
   
      double precision, intent(in) :: a, b
      ! Next variable is of type bundle_t or any extended type of bundle_t
      class(bundle_t), intent(in) :: bundle
      interface
         function f(x, bundle)
            import
            double precision, intent(in) :: x
            class(bundle_t), intent(in) :: bundle
            double precision :: f
         end function f
      end interface
      double precision :: solve
      
      double precision :: xlo, xhi, x, flo, fhi, fn
      
      ! Bisection (I'm assuming a >= b)
      xlo = a
      xhi = b
      flo = f(xlo, bundle)
      fhi = f(xhi, bundle)
      do
         x = 0.5d0*(xlo + xhi)      
         fn = f(x, bundle)
         if (fn > 0.0d0 .eqv. fhi > flo) then
            xhi = x
         else
            xlo = x
         end if
         if (xhi - xlo < 1.0d-5) exit
      end do

      solve = x

   end function solve
   
end module solver

module problem

   use solver

   private

   ! An extended data type is created to store the "problem data".
   type, extends(bundle_t) :: data_t
      double precision :: c
   end type data_t
   
   public :: xxx

contains

   subroutine xxx
   
      type(data_t) :: data
   
      ! The constant in the equation to be solved.
      data%c = 1.0d0
   
      print *, solve(f, 0.0d0, 2.0d0, data)
      
   end subroutine xxx

   function f(x, bundle)
      double precision, intent(in) :: x
      class(bundle_t), intent(in) :: bundle
      double precision :: f
      select type (bundle)
      type is (data_t)
      f = x**2 - bundle%c
      end select
   end function f

end module problem

program anon

   use problem
   
   call xxx
   
end program anon
--
David

Re: Debugging OOP

David,

The underlying debugger, GNU Debugger, is apparently failing when trying to analyze the variable bundle declared as an abstract class.  You'll notice that under "Variables" on the Debugging panel, the variables bundle and all other locals following it alphabetically are not listed.  Furthermore, GDB is completely locking up while trying to deal with this error.  I'll have to look into what's gone wrong; we're not using mainline GDB with Simply Fortran because mainline GDB was not supporting allocatable variables a year or more back.

Jeff Armstrong
Approximatrix, LLC

Re: Debugging OOP

Jeff,

It would be great if something could be done. Maybe allocatable variables are supported now on the main branch?

--
David

Re: Debugging OOP

David,

They are supposedly supported in development versions, but it seems that they are not treated the same as other variables as far as I can tell.  However, the problem with abstract variables seems to persist in the development version.  For that reason, I'll probably proceed with fixing the version we ship for consistency.

Jeff Armstrong
Approximatrix, LLC

Re: Debugging OOP

David,

The problem was due to the internal definition of abstract variables in the GNU debugger for Fortran.  For some reason, the "type" of an abstract variable contained a pointer to its parent type, and it's parent type was itself.  When it attempts to perform the necessary bookkeeping for our front end, it walks up the tree of types, but, as I mentioned, the parent type was itself.  This climbing the tree, therefore, caused an infinite loop within GDB itself.  Simply cutting off the infinite loop by making sure the parent type isn't itself seems to fix the problem with locking up.  I'll be making sure there are no other side effects over the next few days, and version 2.26 will contain the corrected debugger.

Jeff Armstrong
Approximatrix, LLC

Re: Debugging OOP

Jeff,

Thanks. I will wait for 2.26.

--
David

Re: Debugging OOP

I can confirm this is now working. Thanks very much Jeff.

--
David

Re: Debugging OOP

I am having the debugger freeze-up problem with version 2.31 build 2290 GNU Fortran 6.1.0. My code is all Fortran 77 with the exception of the main subroutine.

Re: Debugging OOP

By "freeze-up," what exactly do you mean?  If you wish, you can send along some example code that causes this behavior, and we'll be happy to sort the bug out.

Jeff Armstrong
Approximatrix, LLC

Re: Debugging OOP

I was wrong, the debugger did not freeze up. My program was waiting for a text input but the dialog window was covered up by the other windows. My apologies. Great product.