Dr. Memory
Unaddressable Access

Dr. Memory considers any read or write of a memory location that was not allocated as an "unaddressable access". An allocation is:

  • A call to mmap (or mremap) (or Windows equivalents VirtualAlloc or MapViewOfFile) outside of a heap or stack region.
  • A call to malloc (or calloc or realloc, or Windows equivalents HeapAlloc or HeapReAlloc or the Local or Global versions) inside of a heap region
  • An extension of the stack in a stack region, either via raw instructions or via alloca.

An unaddressable access is an access to an invalid memory address. Examples include a buffer overflow, reading off the end of an array, reading or writing to memory that has been freed (often referred to as a "use-after-free" error), reading beyond the top of the stack, etc.

The heap allocator may pad the size requested by the application. The padded region beyond what the application asked for is considered unaddressable by Dr. Memory.

Consider this example code:

char *x = malloc(8);
char c = *(x+8);

Here is a diagram of the resulting heap allocation:
malloc header: unaddressable
x: uninitialized
x + 8: unaddressable

Dr. Memory will report an unaddressable access error on the second line of the example code, because x+8 is not an addressable location.

When an unaddressable access occurs in a heap region, Dr. Memory attempts to provide additional information about nearby valid allocations and whether the target address is inside a region that has been freed. For example, here is a sample error report:

Error #1: UNADDRESSABLE ACCESS beyond heap bounds: reading 0x000a720b-0x000a720c 1 byte(s)
# 0 main [e:\derek\drmemory\git\src\tests\malloc.c:96]
Note: @0:00:01.500 in thread 3808
Note: refers to 1 byte(s) beyond last valid byte in prior malloc
Note: prev lower malloc: 0x000a7208-0x000a720b
Note: instruction: mov 0x03(%edx) -> %al

Note how the "prev lower malloc" ends at 0x000a720b just before the invalid address, indicating a read that went one byte too far, as indicated.

Here is another example, leveraging the on-by-default -delay_frees_stack option to obtain the callstack of the freed memory:

Error #8: UNADDRESSABLE ACCESS of freed memory: reading 0x001338a8-0x001338ac 4 byte(s)
# 0 unaddr_test1 [e:\derek\drmemory\git\src\tests\suppress.c:110]
# 1 test [e:\derek\drmemory\git\src\tests\suppress.c:269]
# 2 main [e:\derek\drmemory\git\src\tests\suppress.c:297]
Note: @0:00:02.141 in thread 3024
Note: next higher malloc: 0x001338e8-0x00133938
Note: prev lower malloc: 0x001337e8-0x00133820
Note: 0x001338a8-0x001338ac overlaps memory 0x001338a8-0x001338c4 that was freed here:
Note: # 0 test [e:\derek\drmemory\git\src\tests\suppress.c:269]
Note: # 1 main [e:\derek\drmemory\git\src\tests\suppress.c:297]
Note: instruction: mov (%eax) -> %eax

The -brief option provides less information but may be easier to read:

Error #8: UNADDRESSABLE ACCESS of freed memory: reading 4 byte(s)
# 0 unaddr_test1 [e:\derek\drmemory\git\src\tests\suppress.c:110]
# 1 test [e:\derek\drmemory\git\src\tests\suppress.c:269]
# 2 main [e:\derek\drmemory\git\src\tests\suppress.c:297]
Note: refers to memory that was freed here:
Note: # 0 test [e:\derek\drmemory\git\src\tests\suppress.c:269]
Note: # 1 main [e:\derek\drmemory\git\src\tests\suppress.c:297]

The callstack_style option can be used to customize how callstacks are printed out. Here is another style for the same callstack (without -brief):

Error #8: UNADDRESSABLE ACCESS of freed memory: reading 0x001338a8-0x001338ac 4 byte(s)
# 0 unaddr_test1 (0x0040130b <suppress.exe+0x130b>)
e:\derek\drmemory\git\src\tests\suppress.c:110
# 1 test (0x0040112d <suppress.exe+0x112d>)
e:\derek\drmemory\git\src\tests\suppress.c:269
# 2 main (0x0040107e <suppress.exe+0x107e>)
e:\derek\drmemory\git\src\tests\suppress.c:297
Note: @0:00:01.453 in thread 4088
Note: next higher malloc: 0x001338e8-0x00133938
Note: prev lower malloc: 0x001337e8-0x00133820
Note: 0x001338a8-0x001338ac overlaps memory 0x001338a8-0x001338c4 that was freed here:
Note: # 0 test (0x00401121 <suppress.exe+0x1121>)
Note: e:\derek\drmemory\git\src\tests\suppress.c:269
Note: # 1 main (0x0040107e <suppress.exe+0x107e>)
Note: e:\derek\drmemory\git\src\tests\suppress.c:297
Note: instruction: mov (%eax) -> %eax

In this case Dr. Memory is able to report that the target address is inside a malloc area that has been freed and has not been re-allocated since.

An unaddressable access beyond the top of the stack is reported as such:

Error #1: UNADDRESSABLE ACCESS beyond top of stack: reading 0xe6ffb250-0xe6ffb254 4 byte(s)
# 0 process [/work/drmemory/git/src/tests/pthreads.c:79]
# 1 libpthread.so.0!start_thread
# 2 libc.so.6!__clone
Note: @0:00:00.109 in thread 11895
Note: 0xe6ffb250 refers to 208 byte(s) beyond the top of the stack 0xe6ffb320
Note: instruction: mov 0xffffffe8(%ebp,%eax,4) -> %ebx

This additional information, and the addresses accessed, only apply to the first error with that callstack that Dr. Memory sees. Any subsequent errors with the same callstack will increment the duplicate count for that error but further individual information about each duplicate is not provided.