1
Programming Overview of OOMMF
2
Platform-Independent Make Operational Details
3
OOMMF Variable Types and Macros
4
OOMMF eXtensible Solver
5
Debugging OOMMF
5.1
Configuration Files
5.2
Log Messages
5.3
Understanding
pimake
5.4
Bypassing the
oommf.tcl
bootstrap
5.5
Segfaults and other asynchronous termination
5.6
Out-of-bounds memory access
5.7
C++ source code debuggers
Credits
Bibliography
Index
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.