Vulkan Memory Allocator
Debugging incorrect memory usage

If you suspect a bug with memory usage, like usage of uninitialized memory or memory being overwritten out of bounds of an allocation, you can use debug features of this library to verify this.

Memory initialization

If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used, you can enable automatic memory initialization to verify this. To do it, define macro VMA_DEBUG_INITIALIZE_ALLOCATIONS to 1.

#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
#include "vk_mem_alloc.h"

It makes memory of all new allocations initialized to bit pattern 0xDCDCDCDC. Before an allocation is destroyed, its memory is filled with bit pattern 0xEFEFEFEF. Memory is automatically mapped and unmapped if necessary.

If you find these values while debugging your program, good chances are that you incorrectly read Vulkan memory that is allocated but not initialized, or already freed, respectively.

Memory initialization works only with memory types that are HOST_VISIBLE. It works also with dedicated allocations. It doesn't work with allocations created with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag, as they cannot be mapped.

Margins

By default, allocations are laid out in memory blocks next to each other if possible (considering required alignment, bufferImageGranularity, and nonCoherentAtomSize).

Allocations without margin

Define macro VMA_DEBUG_MARGIN to some non-zero value (e.g. 16) to enforce specified number of bytes as a margin before and after every allocation.

#define VMA_DEBUG_MARGIN 16
#include "vk_mem_alloc.h"

Allocations with margin

If your bug goes away after enabling margins, it means it may be caused by memory being overwritten outside of allocation boundaries. It is not 100% certain though. Change in application behavior may also be caused by different order and distribution of allocations across memory blocks after margins are applied.

The margin is applied also before first and after last allocation in a block. It may occur only once between two adjacent allocations.

Margins work with all types of memory.

Margin is applied only to allocations made out of memory blocks and not to dedicated allocations, which have their own memory block of specific size. It is thus not applied to allocations made using VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag or those automatically decided to put into dedicated allocations, e.g. due to its large size or recommended by VK_KHR_dedicated_allocation extension. Margins are also not active in custom pools created with VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag.

Margins appear in JSON dump as part of free space.

Note that enabling margins increases memory usage and fragmentation.

Corruption detection

You can additionally define macro VMA_DEBUG_DETECT_CORRUPTION to 1 to enable validation of contents of the margins.

#define VMA_DEBUG_MARGIN 16
#define VMA_DEBUG_DETECT_CORRUPTION 1
#include "vk_mem_alloc.h"

When this feature is enabled, number of bytes specified as VMA_DEBUG_MARGIN (it must be multiply of 4) before and after every allocation is filled with a magic number. This idea is also know as "canary". Memory is automatically mapped and unmapped if necessary.

This number is validated automatically when the allocation is destroyed. If it is not equal to the expected value, VMA_ASSERT() is executed. It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, which indicates a serious bug.

You can also explicitly request checking margins of all allocations in all memory blocks that belong to specified memory types by using function vmaCheckCorruption(), or in memory blocks that belong to specified custom pool, by using function vmaCheckPoolCorruption().

Margin validation (corruption detection) works only for memory types that are HOST_VISIBLE and HOST_COHERENT.