Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/johnsonjh/duma
duma: Detect Unintended Memory Access (D.U.M.A.) - A Red-Zone memory allocator
https://github.com/johnsonjh/duma
allocator c duma leak-detection malloc
Last synced: 12 days ago
JSON representation
duma: Detect Unintended Memory Access (D.U.M.A.) - A Red-Zone memory allocator
- Host: GitHub
- URL: https://github.com/johnsonjh/duma
- Owner: johnsonjh
- License: gpl-2.0
- Created: 2020-08-25T03:57:59.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2024-10-23T16:49:35.000Z (15 days ago)
- Last Synced: 2024-10-23T23:43:53.176Z (15 days ago)
- Topics: allocator, c, duma, leak-detection, malloc
- Language: C
- Homepage: https://github.com/johnsonjh/duma
- Size: 10.2 MB
- Stars: 100
- Watchers: 11
- Forks: 10
- Open Issues: 52
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: COPYING-GPL
- Security: SECURITY.md
Awesome Lists containing this project
README
# DUMA
---
[![license-gplv2](https://img.shields.io/badge/license-GPL%20v2-blue.svg)](https://github.com/johnsonjh/duma/blob/master/COPYING-GPL)
[![license-lgplv2.1](https://img.shields.io/badge/license-LGPL%20v2.1-blue.svg)](https://github.com/johnsonjh/duma/blob/master/COPYING-LGPL)
[![fossastatus](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fjohnsonjh%2Fduma.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fjohnsonjh%2Fduma?ref=badge_shield)
[![codesize](https://img.shields.io/github/languages/code-size/johnsonjh/duma.svg)](https://github.com/johnsonjh/duma)
[![release](https://img.shields.io/github/release/johnsonjh/duma.svg)](https://github.com/johnsonjh/duma/releases/)
[![codacy](https://api.codacy.com/project/badge/Grade/f777934d666b4a6a9672d89b404c4953)](https://app.codacy.com/gh/johnsonjh/duma?utm_source=github.com&utm_medium=referral&utm_content=johnsonjh/duma&utm_campaign=Badge_Grade)
[![codebeat](https://codebeat.co/badges/a0be6809-acda-41a7-96a8-0d46698dc42c)](https://codebeat.co/projects/github-com-johnsonjh-duma-master)
[![deepscan](https://deepscan.io/api/teams/12184/projects/15170/branches/299583/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=12184&pid=15170&bid=299583)---
## Detect Unintended Memory Access
A Red-Zone memory allocator
---
- [DUMA](#duma)
- [Detect Unintended Memory Access](#detect-unintended-memory-access)
- [Description](#description)
- [Installation](#installation)
- [Binary Packages](#binary-packages)
- [Building from source](#building-from-source)
- [GNU Make](#gnu-make)
- [CMake](#cmake)
- [Visual Studio](#visual-studio)
- [Environment Notes](#environment-notes)
- [Solaris](#solaris)
- [BSD](#bsd)
- [ARM CPUs](#arm-cpus)
- [MIPS CPUs](#mips-cpus)
- [RISC-V CPUs](#risc-v-cpus)
- [Usage](#usage)
- [Static linking](#static-linking)
- [Dynamic linking](#dynamic-linking)
- [Recommended Usage](#recommended-usage)
- [Global and Environment Variables](#global-and-environment-variables)
- [Word-Alignment and Overrun Detection](#word-alignment-and-overrun-detection)
- [Catching the Erroneous Line](#catching-the-erroneous-line)
- [Live (debugger control)](#live-debugger-control)
- [Post-mortem (core analysis)](#post-mortem-core-analysis)
- [Debugging your Program](#debugging-your-program)
- [General Debugging Instructions](#general-debugging-instructions)
- [Word-Alignment and Overrun Debugging](#word-alignment-and-overrun-debugging)
- [Memory Usage and Execution Speed](#memory-usage-and-execution-speed)
- [Memory Leak Detection](#memory-leak-detection)
- [C++ Memory Operators and Leak Detection](#c-memory-operators-and-leak-detection)
- [Definition of own member new/delete Operators](#definition-of-own-member-newdelete-operators)
- [Compilation Notes for Release/Production](#compilation-notes-for-releaseproduction)
- [NO WARRANTY](#no-warranty)
- [Diagnostics](#diagnostics)
- [Bugs](#bugs)
- [Comparison with other tools](#comparison-with-other-tools)
- [Availability](#availability)
- [Releases](#releases)
- [Git Repositories](#git-repositories)
- [Issue Tracking](#issue-tracking)
- [Security Policy](#security-policy)
- [Authors](#authors)
- [License](#license)
- [Version History](#version-history)---
### Description
**DUMA** helps you detect two of the most common programming errors:
1. Software that overruns the boundaries of a `malloc()` memory allocation,
2. Software that touches memory allocations already released by `free()`.Unlike other `malloc()` debuggers, **DUMA** will detect read accesses as well as
writes, and it will pinpoint the exact instruction that causes an error.**Electric Fence**, the predecessor of **DUMA**, has been in use at _Pixar_
since 1987, and at many other sites for years.**DUMA** uses the virtual memory hardware of your computer to place an
inaccessible memory page immediately after (_or before, at the user's option_)
each memory allocation. When software reads or writes this inaccessible page,
the hardware issues a segmentation fault, stopping the program at the offending
instruction. It is then trivial to find the erroneous statement using your
favorite debugger. In a similar manner, memory that has been released by
`free()` is made inaccessible, and any code that touches it will get a
segmentation fault.Simply linking your application with `libduma.a` will allow you to detect most,
but not all, `malloc()` buffer overruns and accesses of free memory. If you want
to be reasonably sure that you've found all catch-able bugs of this type, you'll
have to read and understand the rest of the documentation.Besides catching these kind of memory bugs, **DUMA** also provides a means to
detect memory leaks. When using **DUMA** to pinpoint the source of a
memory-leak, some source modification is necessary - at the minimum, adding
`#include "duma.h"` to your source.---
### Installation
**DUMA** may be installed from compiled binary packages or built
from source code.---
#### Binary Packages
- [***TODO: Binary packages***]
- Packages available for installation via the distribution's package manager:\
[![Available distro packages](https://repology.org/badge/vertical-allrepos/duma.svg?header=)](https://repology.org/project/duma/packages)---
#### Building from source
- The latest release version of **DUMA** is available to download from
[GitHub](https://github.com/johnsonjh/duma/releases/latest)
and [other mirrors](https://github.com/johnsonjh/duma#releases).- _NOTE_: If the latest release version is more than a few dozen commits
behind the master branch, you may wish to try the master branch instead
of the last release. While there are no guarantees made (for any release
of **DUMA**), best efforts are put forth to ensure the master branch
is functional and passes tests on Linux and Solaris.
- Pre-release versions are also available from
[GitHub](https://github.com/johnsonjh/duma/releases) and others mirrors.- You can use the _Git_ distributed version control tool to download
the latest release version, the current development version, or the
entire history, from any of several
[source code repositories](https://github.com/johnsonjh/duma#git-repositories).---
##### GNU Make
**DUMA** may be built using **_GNU_** **Make**.
**_GNU_** **Make** is available for many operating systems, including
_SunOS_ / _Solaris_, _GNU/Hurd_, _AIX_, _HP-UX_, _BSD_, _GNU/Linux_, and
_Microsoft Windows_ (using _Cygwin_ or _UWIN_ for POSIX compatibility, or
natively with the _MSYS_ / _MINGW_ environment.)**_GNU_** **Make** is often installed as `gmake`, but may be installed under
a different name, such as `mingw32-make`, `mingw64-gmake`, or simply `make`
(_especially on_ **_GNU_** _systems such as Linux_).Some **_non_**-**_GNU_** "**Make**" systems **_may_** work, but are
**_untested_** and **not** **recommended** for building **DUMA**.- Inside the unpacked **DUMA** source directory, create and change to a
new `build` directory
- `mkdir build && cd build`
- (_Optionally_) review `GNUmakefile` for configuration, compilation,
and installation options
- Check the `OS` and `OSTYPE` options
(_necessary if automated detection is unsuccessful_)
- Check any other options or variables that may be available
- Build **DUMA**
- `gmake -f ../GNUmakefile srcdir=../`
(_for automatic OS detection and defaults; assumes gmake is GNU Make_)
- `make -f ../GNUmakefile srcdir=../ OSTYPE=cygwin`
(_for Microsoft Windows with Cygwin_)
- `mingw32-make -f ../GNUmakefile srcdir=../ OSTYPE=msys`
(_for Microsoft Windows with MSYS / MINGW via Command Prompt (CMD)_)
- `make -f ../GNUmakefile srcdir=../ OS=linux`
(_for most GNU/Linux systems_)
- Test **DUMA**
- `gmake -f ../GNUmakefile check`
- Install **DUMA**
- `gmake -f ../GNUmakefile install DESTDIR=/opt/duma`
- It may be necessary to prefix this command with
**_su_**, **_sudo_**, **_doas_**, _etc._ to elevate privileges,
depending on the specified `DESTDIR` or `prefix`
- Test **DUMA** installation
- `gmake -f ../GNUmakefile installcheck`---
##### CMake
**CMake** is a portable suite of tools to automate the configuration,
building, testing, packaging, and installation of software.**DUMA** may be built using **CMake** 3.1 (_December 2014_) or later.
- Inside the unpacked **DUMA** source directory, create and change to a
new `build` directory
- `mkdir build && cd build`
- (_Optionally_) interactively configure compilation and installation options
- `ccmake ..` _or_
- `ccmake-gui ..`
- Generate the necessary build files
- `cmake ..`
- You may also specify options non-interactively, for example
- `cmake -DCMAKE_BUILD_TYPE="Debug" ..`
- `cmake -DCMAKE_BUILD_TYPE="Release" ..`
- `cmake -DCMAKE_INSTALL_PREFIX="/opt/duma" ..`
- `cmake -DCMAKE_TOOLCHAIN_FILE=/opt/gcc/toolchain_gcc-8.cmake ..`
- `cmake -G "Visual Studio 16 2019" -A "x64" ..`
- _Refer to the
[CMake Manual](https://cmake.org/cmake/help/latest/manual)
for full details_
- Build **DUMA**
- `cmake --build .`
- Test **DUMA**
- `ctest` (_add_ `-V` _or_ `-VV` _for more verbose output_)
- Install **DUMA**
- `cmake --build . --target "install"`
- It may be necessary to prefix this command with
**_su_**, **_sudo_**, **_doas_**, _etc._ to elevate privileges,
depending on the configured `CMAKE_INSTALL_PREFIX`---
##### Visual Studio
- Compile and execute `createconf`
- Verify the `duma_config.h` header file generated by `createconf`
- Compile `dumalib`
- Customize your project's `INCLUDE` and `LIBS` variables, as required
for your environment---
#### Environment Notes
**DUMA** should work out of the box on most systems, however, specific
environments may require additional configuration or warrant special
consideration.---
##### Solaris
- Both _SPARC_ and _Intel_ processors are supported.
- **DUMA** is tested on _Solaris_ using the GNU toolchain
(_GNU CC, G++, ld, binutils, etc._)- Older _Solaris_ systems, such as _Solaris 10_, using the GNU tools from
the _Companion CD_ should add `/opt/sfw/bin` and `/opt/sfw/lib/bin` to
the `PATH`.- Newer _Solaris_ systems, such as _Solaris 11.next_ or _OpenIndiana_,
require similar configuration.- The _Solaris Studio_ toolchain has not been tested.
---
##### BSD
- **FreeBSD**
- On _FreeBSD_ 6.2, it is necessary to set `DUMA_DISABLE_BANNER=1`
before running any program linked with **DUMA**.
- NOTE: On _FreeBSD_ 7.0 and later, there appears to be an
incompatability with the new libthr, which is currently being
investigated.---
- **NetBSD**
- On _NetBSD_ 3.1 (`HOSTTYPE=i386` / `OSTYPE=netbsdelf`), one (`1`)
memory leak is always detected.- Installation on _NetBSD_ is untested.
---
##### ARM CPUs
- On systems with _ARM_ processors, it may be necessary to set the
`DUMA_MEMCPY_OVERLAP` variable, which allows overlapping of `memcpy()`
regions when the destination address is less than the source address.---
##### MIPS CPUs
- On systems with 64-bit _MIPS_ processors (_MIPS_-_III_ / _IV_ / _V_, _MIPS64_,
_КОМДИВ-64_, _OCTEON_, _VR43xx_, _ICE9_), it may be necessary to explicitly
set the `DUMA_ALIGNMENT` environment variable to eight (`8`) bytes.---
##### RISC-V CPUs
- On systems using _RISC-V_ processors, the base instruction set uses only
fixed-length 32-bit instructions that must be aligned on four (`4`) byte
(_32-bit_) boundaries.- However, the standard _RISC-V_ encoding scheme supports _compressed_
and _variable-length_ instructions. These instructions can be any
number of 16-bit _"instruction parcels"_ in length, and are always
aligned on two (`2`) byte (_16-bit_) boundaries.- The _RISC-V_ processor will not fault when accessing an invalid (_unaligned_)
address. Instead, it will simply use the next valid address. The `DUMA_ALIGNMENT`
environment variable should be set to a value greater than one (`1`)
on systems using _RISC-V_ processors.---
### Usage
#### Static linking
- Link your program with the library `libduma.a`. Make sure you are not linking
with `-lmalloc`, `-lmallocdebug`, or with other `malloc()` debugger or
enhancer libraries. You can only use one at a time.- If your system administrator has installed **DUMA** for public use, you'll be
able to use the `-lduma` argument to the linker, otherwise you'll have to put
the path-name for `libduma.a` in the linker's command line.---
#### Dynamic linking
- If you're using a Bourne-style shell on
most _UNIX_ systems, the statement `export LD_PRELOAD=libduma.so` will cause
**DUMA** to be loaded to run all dynamic executables.- For _Darwin_-based
systems such as macOS X, use `export DYLD_INSERT_LIBRARIES=libduma.dylib`
and `export DYLD_FORCE_FLAT_NAMESPACE=1`.- The included helper command `duma ` will run a single command
under **DUMA**.- For more details, review the documentation for the dynamic linking
facility provided by your operating system vendor.---
#### Recommended Usage
- Some systems will require special arguments to the linker to assure that you
are using the **DUMA** `malloc()` and not the one from your C library.- Run your program using a debugger. It's easier to work this way than to create
a core file and post-mortem debug it. **DUMA** can create huge core files, and
some operating systems will thus take minutes simply to dump core! Some
operating systems will not create usable core files from programs that are
linked with **DUMA**.- If your program has one of the errors detected by **DUMA**, it will get a
segmentation fault (`SIGSEGV`) at the offending instruction. Use the debugger
to locate the erroneous statement, and repair it.---
#### Global and Environment Variables
**DUMA** has several configuration switches that can be enabled via the shell
environment. These switches change what bugs **DUMA** will detect, so it's
important that you know how to use them.- You can use the `gdb` command `'set environment variable value'` to set shell
environment variables only for the program you are going to debug. This is
useful especially if you are using the shared **DUMA** library.- `DUMA_ALIGNMENT` - This is an integer that specifies the alignment for any
memory allocations that will be returned by malloc(), calloc(), and realloc().
The value is specified in bytes, thus a value of 4 will cause memory to be
aligned to 32-bit boundaries unless your system doesn't have a 8-bit
characters. `DUMA_ALIGNMENT` is set to the minimum required alignment specific
to your environment by default. The minimum required alignment is detected by
`createconf` and stored in the file `duma_config.h`.If your program requires that allocations be aligned to 64-bit boundaries
you'll have to set this value to 8. This is the case when compiling with the
`-mips2` flag on _MIPS_-based systems such as those from _SGI_. For some
architectures the default is defined to even more - x86‑64 uses alignment to
16 bytes by default.**DUMA** internally uses a smaller value if the requested memory size is
smaller than the alignment value: the next smaller power of 2 is used.Thus allocating blocks smaller than `DUMA_ALIGNMENT` may result into smaller
alignments - for example when allocating 3 bytes, they would be aligned to 2
byte boundary. This allows better detection of overrun.For this reason, you will sometimes want to set `DUMA_ALIGNMENT` to `1` (no
alignment), so that you can detect overruns of less than your CPU's word size.
Be sure to read the section '_Word-Alignment and Overrun Detection_' in this
manual page before you try this.To change this value, set `DUMA_ALIGNMENT` in the shell environment to an
integer value, or call the macro function `DUMA_SET_ALIGNMENT()` from your
code.You don't need to change this setting, if you just need bigger alignment for
some special buffers. In this case you may use the function
`memalign(alignment, userSize)`.- `DUMA_PROTECT_BELOW` - **DUMA** usually places an inaccessible page
immediately after each memory allocation, so that software that runs past the
end of the allocation will be detected. Setting `DUMA_PROTECT_BELOW` to `1`
causes **DUMA** to place the inaccessible page before the allocation in the
address space, so that under-runs will be detected instead of over-runs.To change this value, set `DUMA_PROTECT_BELOW` in the shell environment to an
integer value, or call the macro function `DUMA_SET_PROTECT_BELOW()` from your
code.- `DUMA_SKIPCOUNT_INIT` - **DUMA** usually does its initialization with the
first memory allocation. On some systems this may collide with initialization
of pthreads or other libraries and produce a hang. To get **DUMA** work even in
these situations you can control (with this environment variable) after how
many allocations the full internal initialization of **DUMA** is done. Default
is `0`.- `DUMA_REPORT_ALL_LEAKS` - **DUMA** usually reports only memory leaks where the
source file-name with line number of the allocating instruction is known.
Setting this variable to `1` in shell environment reports all memory leaks.
The default is `0` to avoid reporting of irrelevant memory leaks from
system/compiler environment: there are many standard libraries leaking memory,
which by default is no real problem as the system frees up all memory on
program exit.- `DUMA_FILL` - When set to a value between `0` and `255`, every byte of
allocated memory is initialized to that value. This can help detect reads of
uninitialized memory. When set to `-1`, **DUMA** does not initialize memory on
allocation, so some memory may filled with zeroes (the operating system
default on most systems) and some memory will retain the values written to it
during its last use.Per default, **DUMA** will initialize all allocated bytes to `255` (`0xFF`).
To change this value, set `DUMA_FILL` in the shell environment to an integer
value, or call the macro function `DUMA_SET_FILL()` from your code.- `DUMA_SLACKFILL` - As **DUMA** internally allocates memory in whole pages,
there retains an unused and unprotectable piece of memory: the slack or
_no-mans-land_. Per default **DUMA** will initialize this area to `170`
(`0xAA`), which is `10101010` in binary representation.To change this value, set `DUMA_SLACKFILL` in the shell environment to an
integer value.**DUMA** automatically checks this area, the _no-mans-land_, at deallocation.
You can manually induce a check with the macro function `DUMA_CHECK()` for one
memory block. With the macro function `DUMA_CHECKALL()` all memory blocks get
checked.- `DUMA_CHECK_FREQ` - First see `DUMA_SLACKFILL` above for definition of
_no-mans-land_. Checking the integrity of the*no-mans-land* costs
performance. This is why this is usually done only at deallocation of a memory
block. Set this variable to let **DUMA** check all memory blocks
_no-mans-land_ every *value*th allocation or deallocation. Set this variable
to 1, to let **DUMA** check at each allocation and deallocation.Per default the value `0` is used, which means to check only at deallocation.
- `DUMA_ALLOW_MALLOC_0` - Memory allocation of size zero is _ANSI_ conforming,
but, often this is the result of a software bug. For this reason **DUMA** may
trap such calls to malloc() with size zero. I leave this option disabled by
default, but you are free to trap these calls setting the
`DUMA_ALLOC_MALLOC_0` in the shell environment to an integer value.- `DUMA_MALLOC_0_STRATEGY` - This environment variable controls **DUMA**'s
behavior on `malloc(0)`:- `0` - abort program with segfault (previously `ALLOW_MALLOC_0 = 0`)
- `1` - return NULL pointer
- `2` - return always the same pointer to some protected page
- `3` - return mid address of a unique protected page (**_default_**)**_ATTENTION_**: Only `1` and `3` are _ANSI_ conforming. But value `1`
will break most programs, and value `3` strategy most system libraries
use/implement. All returned pointers can be passed to `free()`.- `DUMA_NEW_0_STRATEGY` - This environment variable controls **DUMA**'s
behavior on C++ operator new with size zero:- `2` - return always the same pointer to some protected page
- `3` - return mid address of a unique protected page (**_default_**)**_ATTENTION_**: Only `3` is standard conforming. Value `2` may break
some, but will work for most programs. With value `2` you may reduce the
memory consumption.- `DUMA_MALLOC_FAILEXIT` - Many programs do not check for allocation failure.
This often leads to delayed errors, no more understandable. Set this variable
to a positive integer in the shell environment to exit the program immediately
when memory allocation fails. This option is set by default.- `DUMA_PROTECT_FREE` - **DUMA** usually returns free memory to a pool from
which it may be re-allocated. If you suspect that a program may be touching
free memory, set `DUMA_PROTECT_FREE` shell environment to `-1`. This is the
default and will cause **DUMA** not to re-allocate any memory.For programs with many allocations and de-allocations this may lead to the
consumption of the full address space and thus to the failure of `malloc()`.
It is important to discriminate between _address space_ and _physical memory_;
**DUMA** does free the _physical memory_; but the _address space_ is not
freed. Thus, the _address space_ may be exhausted despite available _physical
memory_. This is especially important on 32-bit systems. To avoid such
failures, you may limit the amount of protected de-allocated memory by setting
`DUMA_PROTECT_FREE` to a positive value. This value in **kB** will be the
limit for such protected free memory.A value of `0` will disable protection of freed memory.
- `DUMA_MAX_ALLOC` - This shell environment variable limits the total memory
print of a program. This is another way to indirectly limit the sum of freed
protected memory (see `DUMA_PROTECT_FREE`). By default there is no limit
(`-1`). A positive value is interpreted in **kB**, which stands for the sum of
allocated and freed protected memory.- `DUMA_FREE_ACCESS` - This is a debugging enhancer to catch deallocation of a
memory block using watch expressions. **DUMA** does a write access to the
first byte, which may lead a debugger to stop on a watch expression. You have
to enable this by setting the shell environment variable to non zero. Default
is disabled.- `DUMA_SHOW_ALLOC` - Set this shell environment variable to non-zero to let
DUMA print all allocations and de-allocations to the console. Although this
generates a lot of messages, this option can be useful to detect inefficient
code containing many (de)allocations. This is switched off by default.- `DUMA_SUPPRESS_ATEXIT` - Set this shell environment variable to non-zero when
DUMA should skip the installation of its exit handler. The exit handler is
called at the end of the main program and checks for memory leaks, so the
handler's installation should **_usually_** not be suppressed. One reason for
doing so regardless are some buggy environments, where calls to the standard C
library's `atexit()`-function hangs.- `DUMA_DISABLE_BANNER` - Set this shell environment variable to non-zero to
suppress the usual start-up message on console. Default is `0`.- `DUMA_OUTPUT_DEBUG` - Set this shell environment variable to non-zero to
output all DUMA messages to the debugging console. This option is only
available on Windows and is off by default.- `DUMA_OUTPUT_STDOUT` - Set this shell environment variable to non-zero to
output all DUMA messages to _STDOUT_. This option is off by default.- `DUMA_OUTPUT_STDERR` - Set this shell environment variable to non-zero to
output all DUMA messages to _STDERR_. This option is on by default.- `DUMA_OUTPUT_FILE` - Set this shell environment variable to a file-name where
all DUMA messages should be written to. This option is off by default.- `DUMA_OUTPUT_STACKTRACE` - Set this shell environment variable to non-zero to
output a stacktrace of the allocation that is not freed. This option is
available only on Windows and is off by default. This option also requires a
map file generated by the linker.- `DUMA_OUTPUT_STACKTRACE_MAPFILE` - Set this shell environment variable to the
map file, when it isn't found. This is very useful when using detours version
of DUMA. This option is available only on Windows.- `DUMA_MEMCPY_OVERLAP` - Set this shell environment variable to allow
overlapping of memcpy regions if the destination address is less than source
address. (workaround for _ARM_ `memmove`/`memcpy` implementation).---
#### Word-Alignment and Overrun Detection
There is a conflict between the alignment restrictions that `malloc()` operates
under and the debugging strategy used by **DUMA**. When detecting overruns,
**DUMA** `malloc()` allocates two or more virtual memory pages for each
allocation. The last page is made inaccessible in such a way that any read,
write, or execute access will cause a segmentation fault. Then, **DUMA**
`malloc()` will return an address such that the first byte after the end of the
allocation is on the inaccessible page. Thus, any overrun of the allocation will
cause a segmentation fault.It follows that the address returned by `malloc()` is the address of the
inaccessible page minus the size of the memory allocation. Unfortunately,
`malloc()` is required to return _word-aligned_ allocations, since many CPUs can
only access a word when its address is aligned. The conflict happens when
software makes a memory allocation using a size that is not a multiple of the
word size, and expects to do word accesses to that allocation. The location of
the inaccessible page is fixed by hardware at a _word-aligned_ address. If
**DUMA** `malloc()` is to return an aligned address, it must increase the size
of the allocation to a multiple of the word size.In addition, the functions `memalign()` and `valloc()` must honor explicit
specifications on the alignment of the memory allocation, and this, as well can
only be implemented by increasing the size of the allocation. Thus, there will
be situations in which the end of a memory allocation contains some padding
space, and accesses of that padding space will not be detected, even if they are
overruns.**DUMA** provides the variable `DUMA_ALIGNMENT` so that the user can control the
default alignment used by `malloc()`, `calloc()`, and `realloc()`. To debug
overruns as small as a single byte, you can set `DUMA_ALIGNMENT` to `1`. This
will result in **DUMA** `malloc()` returning unaligned addresses for allocations
with sizes that are not a multiple of the word size. This is not a problem in
most cases, because compilers must pad the size of objects so that alignment
restrictions are honored when storing those objects in arrays. The problem
surfaces when software allocates odd-sized buffers for objects that must be
_word-aligned_. One case of this is software that allocates a buffer to contain
a structure and a string, and the string has an odd size (this example was in a
popular _TIFF_ library).If word references are made to un-aligned buffers, you will see a bus error
(`SIGBUS`) instead of a segmentation fault. The only way to fix this is to
re-write the offending code to make byte references or not make odd-sized
allocations, or to set `DUMA_ALIGNMENT` to the word size.Another example of software incompatible with `DUMA_ALIGNMENT` set less than
the system _word-size_ is the `strcmp()` function and other string functions
on _SunOS_ 4, which make _word-sized_ accesses to character strings, and may
attempt to access up to three bytes **_beyond_** the end of a string. These
result in a segmentation fault (`SIGSEGV`). The only way around this is to use
versions of the string functions that perform _byte references_ instead of
_word references_.---
### Catching the Erroneous Line
Using **DUMA** - and one of the following strategies - you can determine the
offending line(s) of your source code responsible for causing an error.#### Live (debugger control)
1. Compile your program with debugging information and statically linked to
DUMA. On some systems, including some Linux distributions, the linking order
is crucial - **DUMA** must be the last library passed to the linker.
2. Start your program from debugger e.g. with `gdb `
3. Set program environment variables such as
`'set environment DUMA_PROTECT_BELOW 1'`
4. Set your program arguments with `'set args …'`
5. Run and wait for the segmentation fault#### Post-mortem (core analysis)
1. Compile your program (**_with_** debugging information).
2. Set `ulimit -c unlimited` to get core files
3. Start your program, choose one of following options
- Start your program (linked **_statically_** with **DUMA**)
- Start your program with `duma.sh `
4. Wait for a segmentation fault. This should have created a `core[.]`
file, which you can examine (i.e. `gdb -c `)---
### Debugging your Program
#### General Debugging Instructions
1. Link with `libduma.a` as explained above, ensuring proper linking order.
2. Run your program in a debugger and fix any overruns or accesses to free
memory.
3. Quit the debugger.
4. Set `DUMA_PROTECT_BELOW = 1` in the shell environment.
5. Repeat step 2, this time repairing under-runs if they occur.
6. Quit the debugger.
7. Optionally, read and install `gdbinit.rc` as `~/.gdbinit` if you are using
the `gdb` debugger#### Word-Alignment and Overrun Debugging
- See if you can set `DUMA_ALIGNMENT` to `1`, and repeat step 2.
- Sometimes this will be too much work, or there will be problems with library
routines for which you don't have the source, that will prevent you from
doing this.---
### Memory Usage and Execution Speed
- Since **DUMA** uses at least two virtual memory pages for each of its
allocations, it's a terrible memory hog. It may be necessary to configure a
swap file so the system will have enough virtual memory available. Also, the
way **DUMA** manipulates memory results in various cache and translation
buffer entries being flushed with each call to `malloc()` or `free()`. The end
result is that your program will execute slower and use more resources while
you are debugging it with **DUMA**.- The Linux kernel may limit the number of page mappings per process. See
`/proc/sys/vm/max_map_count`. You may have to increase this value to allow
debugging with **DUMA** with a command such as:
`sysctl -w vm.max_map_count=1000000`- **Don't** leave `libduma.a` enabled and linked in production software. Use it
only for debugging. See the section '_Compilation Notes for
Release / Production_' below.---
### Memory Leak Detection
- All memory allocation is protocol-ed from **DUMA** together with the file-name
and line number of the calling function. The `atexit()` function checks if each
allocated memory block was freed. To disable leak detection add the
preprocessor definition `DUMA_SO_NO_LEAKDETECTION` or
`DUMA_LIB_NO_LEAKDETECTION` to `DUMA_OPTIONS` in the Makefile.- If a leak is reported without a source file-name or line number, but is
reproducible with the same pointer, set a conditional breakpoint on the
function `void * duma_alloc_return( void * address)`, for example, using the
**gdb** command `'break duma_alloc_return if address==0x123'`---
### C++ Memory Operators and Leak Detection
- Macros for "`new`" and "`delete`" are defined in `dumapp.h`. These macros give
file-name and line number of the calling functions to **DUMA**, thus allowing
the same leak detection reports as for `malloc()` and `free()`. `dumapp.h` needs to be
included from your source file(s).- To disable the C++ `new`, `delete`, `new[]`, and `delete[]` operators, add
the preprocessor definition `DUMA_NO_CPP_SUPPORT` to `DUMA_OPTIONS` in
Makefile.---
#### Definition of own member new/delete Operators
- Definition of own member `new`/`delete` operators for a class will fail
because the `new`/`delete` keywords are defined as macros from **DUMA**. You
will have to un-define **DUMA**'s macros with following line:
`#include "noduma.h"` Then you have to call **DUMA**'s operators directly
inside your own definition.- For using **DUMA**'s C++ operators without having the preprocessor macros
defined, following syntax can be used:```c++
// const char * file or __FILE__ macro
// int line or __LINE__ macro// scalar new throwing bad_alloc() on error
ptr = new(file,line) type;// scalar new returning 0 on error
ptr = new(std::nothrow,file,line) type;// scalar delete
operator delete(ptr,file,line);// vector new throwing bad_alloc() on error
ptr = new(file,line) type[n];// vector new returning 0 on error
ptr = new(std::nothrow,file,line) type[n];// vector delete
operator delete[](ptr, file,line);
```---
### Compilation Notes for Release/Production
- Set the preprocessor definition `#define DUMA_NO_DUMA` in your Makefiles to
disable **DUMA** usage - and don't link with **DUMA** library. With
`DUMA_NO_DUMA` defined, all **DUMA** macro functions get defined, but do
nothing.- This way, you don't have to change your code for release compilation, even
when using special **DUMA** macros.---
### NO WARRANTY
- This software has **_NO WARRANTY_**.
- **_See the [license](#license) for complete details._**
- Much effort has been expended to ensure the correctness of **DUMA**,
however, it is (in all likelihood) not theoretically possible to make
software of this nature **_bug-free_**.- **DUMA** **_may not_** report all bugs that exist in your code.
- It may also **_incorrectly_** report bugs that do not exist.
---
### Diagnostics
- **_Segmentation Fault_**: Examine the offending statement for violation of the
boundaries of a memory allocation.- **_Bus Error_**: See the section on _'Word-Alignment and Overrun Detection'_
in this manual.---
#### Bugs
- Explanation of alignment issues could be improved.
- Some **Sun** systems running **SunOS** **4.1** were reported to signal an
access to a protected page with `SIGBUS` rather than `SIGSEGV`. This is
most likely an undocumented "_feature_" of particular _Sun_ hardware
versions, and not an operating system anomaly.
- On these systems **DUMA** tests will fail with a _bus error_ unless the
`Makefile` is modified to define `PAGE_PROTECTION_VIOLATED_SIGNAL`
as `SIGBUS`.---
### Comparison with other tools
- **_[pending]_**
---
### Availability
#### Releases
- [GitHub Releases](https://github.com/johnsonjh/duma/releases)
#### Git Repositories
**_NOTE_**: _All source repositories are mirrors with identical contents._
- [GitHub](https://github.com/johnsonjh/duma)
- [GitLab](https://gitlab.com/johnsonjh/duma)
- [SourceHut](https://sr.ht/~trn/duma)
- [NotABug](https://notabug.org/trn/duma)---
### Issue Tracking
- [GitHub Issue Tracker](https://github.com/johnsonjh/duma/issues)
---
### Security Policy
- [Security Policy and Vulnerability Reporting](https://github.com/johnsonjh/duma/security/policy)
---
### Authors
```text
Copyright © 2020‑2022 Jeffrey H. Johnson
Copyright © 2006 Michael Eddington
Copyright © 2002‑2021 Hayati Ayguen , Procitec GmbH
Copyright © 1987‑1999 Bruce Perens
```---
### License
[![FOSSASmallStatus](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fjohnsonjh%2Fduma.svg?type=small)](https://app.fossa.com/projects/git%2Bgithub.com%2Fjohnsonjh%2Fduma?ref=badge_small)
- [GNU General Public License v2.0 (GPLv2)](https://tldrlegal.com/license/gnu-general-public-license-v2)
- [GNU Lesser General Public License v2.1 (LGPLv2.1)]()
---
### Version History
- [Version History](https://github.com/johnsonjh/duma/blob/master/CHANGELOG.md)
---