5 Debugging OOMMF

5.5 Out-of-bounds memory access

One of the more common coding errors is allowing array access outside the allocated range of an array. This error can be insidious because the program may continue to run past the point of invalid access, but plant a seed that grows into a seemingly unrelated fatal error later on. There are a number of tools designed to uncover this problem, but an especially easy one to use that is common on Linux systems is the venerable Electric Fence, original written by Bruce Perens in 1987. If the libefence.so shared library is installed, then from the bash prompt in the oommf/app/oxs directory you can run

$ LD_PRELOAD=libefence.so linux-x86_64/oxs boxsi.tcl foo.mif
(On some installations there may also be an equivalent shell wrapper ef.) This will abort with a segfault if an invalid memory reference (read or write) is detected. One nice feature is that you don’t have to rebuild OOMMF to use this debugger—the efence shared library transparently replaces the standard system memory allocator with the instrumented Electric Fence version at runtime. If you enable core dumps as explained above, then on Linux systems even without debug symbols a stack trace on the core dump will provide the function call list. If you build OOMMF with debugging symbols (Oc_Option cflags option -debug in config/local/options.tcl), then the core stack trace will give the source file and line number where the invalid memory access occurred. Also, OOMMF runs at normal speed with Electric Fence enabled, so you can use it to check for errors in large simulations.

One caveat is that for performance reasons, OOMMF sometimes allocates larger memory blocks than needed. Electric Fence detects memory accesses outside the requested memory range, so OOMMF accesses of memory outside its proper range but inside the requested range will not be flagged. You can have OOMMF request tight blocks by putting these lines in your local/<platform>.tcl file:

$config SetValue program_compiler_c++_property_cache_linesize 1
$config SetValue program_compiler_c++_property_pagesize 1
$config SetValue sse_no_aligned_access 1

and rebuilding OOMMF (pimake distclean plus pimake).

Normally Electric Fence detects accesses to memory locations above the allocated range (index too high), but you can have it check instead for memory accesses preceding the allocated range (index too low) by setting the environment variable EF_PROTECT_BELOW to 1.

The Electric Fence documentation warns that core dumps of Electric Fence enabled runs can be significantly larger than core dumps without Electric Fence, and so recommends running Electric Fence with the selected executable (here oxs) from inside a debugger rather than creating a core dump. This does not appear to be a problem when used with OOMMF however, as the core dumps with Electric Fence tend to be only modestly larger than those without.

A similar tool on macOS is the gmalloc (Guard Malloc) package, which is included with Xcode. Run it from the oommf/app/oxs bash or zsh command line with

% DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib darwin/oxs boxsi.tcl foo.mif
See the documentation from Apple for full details.