Generating a Backtrace with gfortran

On occasion, when you’re developing in Fortran (or any other compiled language), a program will stop with an error message, and you will be at a loss as to how execution ended up at the line in question. What you need is a backtrace, but because your program didn’t actually crash, no core dump occurs, and no backtrace is available.

If you are using a debugger, you can set a breakpoint and get a backtrace that way. But there are times when using a debugger is not desirable, such as when your program needs to run in parallel, or via a batch queue. If using the debugger is not an option, your next best bet is to force a core dump. If you are compiling with gfortran, this is relatively trivial, provided you know the required steps. So here goes…

On Mac OS X, you first need to set the core dump limit, which by default is 0.

ulimit -c unlimited

Then you need to add a line of code at the point where you wish to core dump.

call abort()

Recompile, and run.

Once your program core dumps, you need to locate the core file in the /cores directory, and then start the gdb debugger.

gdb <path_to_executable> <path_to_core_file>

Once the debugger has loaded the core file, enter the command where in order to get a backtrace. By way of example, here is a real world session:

GNU gdb 6.3.50-20050815 (Apple version gdb-768) (Tue Oct  2 04:11:19 UTC 2007)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "powerpc-apple-darwin"...Reading symbols for shared libraries ...... done

Core was generated by `/Users/cormack/Develop/ADF/adftrunk/bin.debug/adf.exe'.
Reading symbols for shared libraries . done
Reading symbols for shared libraries .......................................................... done
#0  0x95087cb8 in kill$UNIX2003 ()
(gdb) where
#0  0x95087cb8 in kill$UNIX2003 ()
#1  0x9512c7c8 in abort ()
#2  0x00cfc0e0 in _gfortran_abort () at ../.././libgfortran/intrinsics/abort.c:39
#3  0x00c16be4 in getnumcartesiancoordsprot (self=@0x0) at /Users/cormack/Develop/ADF/adftrunk/build/libtc.build/debug/CoordSet.f90:223
#4  0x00c3e4c0 in projectoutrigidmotionsmatrix (coordset=@0x485be00, optimcoordsmatrix=<value temporarily unavailable, due to optimizations>, option=<value temporarily unavailable, due to optimizations>) at /Users/cormack/Develop/ADF/adftrunk/build/libtc.build/debug/OptimizeUtilities.f90:38
#5  0x00c19ab8 in updatehessianprivate (self=@0x485be00, grad=<value temporarily unavailable, due to optimizations>, coords=<value temporarily unavailable, due to optimizations>) at /Users/cormack/Develop/ADF/adftrunk/build/libtc.build/debug/HessianUpdater.f90:392
#6  0x00473ed8 in cinebstepimage (imageindex=@0xbfffe0bc, iter=@0x19e5e80, finished_one=@0xbfffe0b8, egradc=<value temporarily unavailable, due to optimizations>, total_forces=<value temporarily unavailable, due to optimizations>, energy=0x4526c20) at /Users/cormack/Develop/ADF/adftrunk/build/adf.build/debug/Cineb.f90:1654
#7  0x00480a24 in cinebstep (fragments=@0x4810400, finished=@0xbfffe608, dirty_image=0x4526b90, egradc=0x4844800, energy=0x4526c20, iter=@0x19e5e80) at /Users/cormack/Develop/ADF/adftrunk/build/adf.build/debug/Cineb.f90:1526
#8  0x0048406c in cinebmain (initialgeometry=<value temporarily unavailable, due to optimizations>, fragments=@0x4810400) at /Users/cormack/Develop/ADF/adftrunk/build/adf.build/debug/Cineb.f90:278
#9  0x00002324 in adf () at /Users/cormack/Develop/ADF/adftrunk/build/adf.build/debug/adf.f90:109
#10 0x00cde62c in main (argc=1, argv=0xbfffe914) at ../.././libgfortran/fmain.c:21

Don’t forget to remove the call to abort from your source code before moving on!

Comments

Have gfortran emit its own backtrace

On Linux (and all glibc systems), gfortran can emit its own backtrace on runtime errors, segfaults and calls to abort, by compiling with -fbacktrace. On MacOS, it's not currently possible because I don't know any way for a process to retrieve its own calling stack using the system library. But if anyone knows how to do this (if possible), I'd be happy to have it included in the next gfortran version...

Backtrace from code

I found this page that looks like it has one or more solutions:

http://www.cocoadev.com/index.pl?StackTraces

It mentions a few functions that have been added in 10.5 that make things a lot simpler.

Drew

---------------------------
Drew McCormack
http://www.maccoremac.com
http://www.macanics.net
http://www.macresearch.org

Backtrace from code

Yes, they've actually added functions with same name and API as glibc, so I guess it should already be working if you compile gfortran on 10.5.

For those interested, the man pages are at http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/backtrace.3.html