Memory

From FEAP Wiki
Jump to navigation Jump to search

Basics

FEAP's memory management system utilizes an offset technique. There are two (short arrays) hr( ) of type real (kind=8) and mr( ) of type integer, which are both defined in the common block comblk.h. When FEAP arrays are allocated they are done so using the system malloc. This is either done in the source file unix/memory/cmem.c, if on Linux/MAC, or in the source file windows/memory/setmem.f, if on windows.

For each FEAP array that is allocated the offset to its location in memory in units of real*8 or integer chunks of memory is stored in the array np( ). Thus for the DR array, array number 26, which holds the residual, its first element is equivalent to hr(np(26)). For integer arrays like IE, array number 32, which holds the element assembly information, its first element is equivalent to mr(np(32)). In this way FEAP provides a functionality to access all of its internal arrays through a combined use of the common blocks comblk.h and pointer.h, which contains the np( ) array.

Checksumming FEAP arrays

When chasing memory errors under Linux/MAC there are two utility functions that can be helpful. In particular

  call cmemumark(np(xx),precision,ipr)

computes and stores a checksum of the data associated with array xx (set xx to the number of the array you are interested in, set precision to either 1 for integer arrays or 2 for reals, set ipr to 1 for 8 byte integers and 2 for 4 byte integers). You can then check the integrity of the data relative to this checksum at any other place in the code with

  call cmemucheck(np(xx),precision,ipr,result)

where result is an integer =1 for no change and =0 if the data has changed.

Checksumming FEAP array headers

Each FEAP array when allocated is also given a header block, the integrity of the header data to each FEAP array can be checked with

  call cmemcheck(np(xx),precision,ipr)

GDB is your friend

Sometimes data gets overwriting in strange ways and it is very hard to track down when certain arrays are being corrupted. The very best way to debug such problems is to use GDB (or a similar debugger). Make sure that you have compiled the code with the option to generate symbol tables -g on Linux/MAC systems. Then start the code in the debugger gdb feap , set breakpoints and step/continue to see what is going on. GDB is typically installed on Linux systems and if it is not, it can be easily installed with your distributions package manager. If you are on a Mac, here are some brief instructions to authorize GDB on your computer.

A really useful feature is to use the watch command to allow the program to stop whenever a particular memory address is changed. Suppose I am interest on when the first element of the residual array DR (array 26) changes. I would do the following

(gdb) break pnewprob_

to first set a break point in pnewprob where DR is allocated.

(gdb) run

to get going. Then when the program stops

(gdb) break +646

to set a break point after the point where DR has been allocated. Alternately your debugger may accept

(gdb) break pnewprob.f:646
Then,
(gdb) run

Then

(gdb) p np(26)
(gdb) p &hr(1)

to get the offset to DR and the memory address of hr(1). Suppose these were 195297 and 0xd1ba60. Now compute the address of the first element of DR as 195297*8 + 0xd1ba60, the multiplier is 8(bytes) since DR is a double precision real array. Note 195297*8 = 1562376 = 0x17d708. Adding to the base address we get 0xe99168. Now set a watch on this memory location and continue. The program will stop whenever this address location is altered.

(gdb) watch *(double *)0xe99168
(gdb) c

See the GDB manual watchpoint section for additional details.

Valgrind is incredible

A second very valuable debugging tool is Valgrind. This amazing tool can track down virtually any memory issue you may have with amazing efficiency. Your code will run quite slow in valgrind, BUT it will help you locate errors very fast. Just install from the web site or from your package manager (yum, apt, dnf, port, fink, etc.). To run simply type

valgrind feap

Make sure that you have compiled your code with the symbols, -g.