package core:mem

Overview

package mem implements various types of allocators.

An example of how to use the Tracking_Allocator to track subsequent allocations in your program and report leaks and bad frees:

```odin package foo

import "core:mem" import "core:fmt"

_main :: proc() {

do stuff

}

main :: proc() {

track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)

_main()

for _, leak in track.allocation_map {
	fmt.printf("%v leaked %v bytes\n", leak.location, leak.size)
}
for bad_free in track.bad_free_array {
	fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
}

} ```

Index

Variables (0)

This section is empty.

Procedures (99)
Procedure Groups (3)

Types

Allocator ¶

Allocator :: runtime.Allocator

Allocator_Error ¶

Allocator_Error :: runtime.Allocator_Error

Allocator_Mode ¶

Allocator_Mode :: runtime.Allocator_Mode
 

NOTE(bill, 2019-12-31): These are defined in package runtime as they are used in the context. This is to prevent an import definition cycle.

Allocator_Mode_Set ¶

Allocator_Mode_Set :: runtime.Allocator_Mode_Set

Allocator_Proc ¶

Allocator_Proc :: runtime.Allocator_Proc
 

Allocator_Error :: enum byte {

None                 = 0,
Out_Of_Memory        = 1,
Invalid_Pointer      = 2,
Invalid_Argument     = 3,
Mode_Not_Implemented = 4,

}

Allocator_Query_Info ¶

Allocator_Query_Info :: runtime.Allocator_Query_Info

Arena ¶

Arena :: struct {
	data:       []u8,
	offset:     int,
	peak_used:  int,
	temp_count: int,
}

Arena_Temp_Memory ¶

Arena_Temp_Memory :: struct {
	arena:       ^Arena,
	prev_offset: int,
}

Dynamic_Pool ¶

Dynamic_Pool :: struct {
	block_size:           int,
	out_band_size:        int,
	alignment:            int,
	unused_blocks:        [dynamic]rawptr,
	used_blocks:          [dynamic]rawptr,
	out_band_allocations: [dynamic]rawptr,
	current_block:        rawptr,
	current_pos:          rawptr,
	bytes_left:           int,
	block_allocator:      runtime.Allocator,
}

Fixed_Byte_Buffer ¶

Fixed_Byte_Buffer :: distinct [dynamic]u8

Poly_Raw_Map ¶

Poly_Raw_Map :: struct($Key: typeid, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {}

Poly_Raw_Map_Entry ¶

Poly_Raw_Map_Entry :: struct($Key: typeid, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {}

Raw_Any ¶

Raw_Any :: runtime.Raw_Any

Raw_Complex128 ¶

Raw_Complex128 :: struct {
	real,
	imag: f64,
}

Raw_Complex64 ¶

Raw_Complex64 :: struct {
	real,
	imag: f32,
}

Raw_Cstring ¶

Raw_Cstring :: runtime.Raw_Cstring

Raw_Dynamic_Array ¶

Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array

Raw_Map ¶

Raw_Map :: runtime.Raw_Map

Raw_Quaternion128 ¶

Raw_Quaternion128 :: struct {
	imag,
	jmag,
	kmag: f32,
	real: f32,
}

Raw_Quaternion128_Vector_Scalar ¶

Raw_Quaternion128_Vector_Scalar :: struct {
	vector: [3]f32,
	scalar: f32,
}

Raw_Quaternion256 ¶

Raw_Quaternion256 :: struct {
	imag,
	jmag,
	kmag: f64,
	real: f64,
}

Raw_Quaternion256_Vector_Scalar ¶

Raw_Quaternion256_Vector_Scalar :: struct {
	vector: [3]f64,
	scalar: f64,
}

Raw_Slice ¶

Raw_Slice :: runtime.Raw_Slice

Raw_Soa_Pointer ¶

Raw_Soa_Pointer :: runtime.Raw_Soa_Pointer

Raw_String ¶

Raw_String :: runtime.Raw_String

Scratch_Allocator ¶

Scratch_Allocator :: struct {
	data:               []u8,
	curr_offset:        int,
	prev_allocation:    rawptr,
	backup_allocator:   runtime.Allocator,
	leaked_allocations: [dynamic][]u8,
}

Small_Stack ¶

Small_Stack :: struct {
	data:      []u8,
	offset:    int,
	peak_used: int,
}
 

Small_Stack is a stack-like allocator which uses the smallest possible header but at the cost of non-strict memory freeing order

Small_Stack_Allocation_Header ¶

Small_Stack_Allocation_Header :: struct {
	padding: u8,
}

Stack ¶

Stack :: struct {
	data:        []u8,
	prev_offset: int,
	curr_offset: int,
	peak_used:   int,
}
 

Stack is a stack-like allocator which has a strict memory freeing order

Stack_Allocation_Header ¶

Stack_Allocation_Header :: struct {
	prev_offset: int,
	padding:     int,
}

Tracking_Allocator ¶

Tracking_Allocator :: struct {
	backing:           runtime.Allocator,
	allocation_map:    map[rawptr]Tracking_Allocator_Entry,
	bad_free_array:    [dynamic]Tracking_Allocator_Bad_Free_Entry,
	clear_on_free_all: bool,
}

Tracking_Allocator_Bad_Free_Entry ¶

Tracking_Allocator_Bad_Free_Entry :: struct {
	memory:   rawptr,
	location: runtime.Source_Code_Location,
}

Tracking_Allocator_Entry ¶

Tracking_Allocator_Entry :: struct {
	memory:    rawptr,
	size:      int,
	alignment: int,
	err:       runtime.Allocator_Error,
	location:  runtime.Source_Code_Location,
}

Constants

Byte ¶

Byte :: 1

DEFAULT_ALIGNMENT ¶

DEFAULT_ALIGNMENT :: 2 * align_of(rawptr)

DEFAULT_PAGE_SIZE ¶

DEFAULT_PAGE_SIZE :: 64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64 else 16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else 4 * 1024

DEFAULT_RESERVE_CAPACITY ¶

DEFAULT_RESERVE_CAPACITY :: 16

DYNAMIC_POOL_BLOCK_SIZE_DEFAULT ¶

DYNAMIC_POOL_BLOCK_SIZE_DEFAULT :: 65536

DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT ¶

DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: 6554

Gigabyte ¶

Gigabyte :: 1024 * Megabyte

Kilobyte ¶

Kilobyte :: 1024 * Byte

Megabyte ¶

Megabyte :: 1024 * Kilobyte

Terabyte ¶

Terabyte :: 1024 * Gigabyte

Variables

This section is empty.

Procedures

align_backward ¶

align_backward :: proc "odin" (ptr: rawptr, align: uintptr) -> rawptr {…}

align_backward_int ¶

align_backward_int :: proc "odin" (ptr, align: int) -> int {…}

align_backward_uint ¶

align_backward_uint :: proc "odin" (ptr, align: uint) -> uint {…}

align_backward_uintptr ¶

align_backward_uintptr :: proc "odin" (ptr, align: uintptr) -> uintptr {…}

align_formula ¶

align_formula :: proc "contextless" (n, k: int) -> int {…}

align_forward ¶

align_forward :: proc "odin" (ptr: rawptr, align: uintptr) -> rawptr {…}

align_forward_int ¶

align_forward_int :: proc "odin" (ptr, align: int) -> int {…}

align_forward_uint ¶

align_forward_uint :: proc "odin" (ptr, align: uint) -> uint {…}

align_forward_uintptr ¶

align_forward_uintptr :: proc "odin" (ptr, align: uintptr) -> uintptr {…}

alloc ¶

alloc :: proc "odin" (size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {…}

alloc_bytes ¶

alloc_bytes :: proc "odin" (size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, runtime.Allocator_Error) {…}

any_to_bytes ¶

any_to_bytes :: proc "contextless" (val: any) -> []u8 {…}

arena_allocator ¶

arena_allocator :: proc "odin" (arena: ^Arena) -> runtime.Allocator {…}

arena_allocator_proc ¶

arena_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

arena_init ¶

arena_init :: proc "odin" (a: ^Arena, data: []u8) {…}

begin_arena_temp_memory ¶

begin_arena_temp_memory :: proc "odin" (a: ^Arena) -> Arena_Temp_Memory {…}

buffer_from_slice ¶

buffer_from_slice :: proc "contextless" (backing: $T/[]$) -> [dynamic]$ {…}

byte_slice ¶

byte_slice :: proc "contextless" (data: rawptr, len: int) -> []u8 {…}

calc_padding_with_header ¶

calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, header_size: int) -> int {…}

check_zero ¶

check_zero :: proc "odin" (data: []u8) -> bool {…}

check_zero_ptr ¶

check_zero_ptr :: proc "odin" (ptr: rawptr, len: int) -> bool {…}

clone_slice ¶

clone_slice :: proc "odin" (slice: $T/[]$, allocator := context.allocator, loc := #caller_location) -> (new_slice: $T/[]$) {…}

compare ¶

compare :: proc "contextless" (a, b: []u8) -> int {…}

compare_byte_ptrs ¶

compare_byte_ptrs :: proc "contextless" (a, b: ^u8, n: int) -> int {…}

compare_ptrs ¶

compare_ptrs :: proc "contextless" (a, b: rawptr, n: int) -> int {…}

context_from_allocator ¶

context_from_allocator :: proc "odin" (a: runtime.Allocator) -> runtime.Context {…}

copy ¶

copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {…}

copy_non_overlapping ¶

copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {…}

default_resize_align ¶

default_resize_align :: proc "odin" (
	ptr:                rawptr, 
	old_size, new_size: int, 
	alignment:          int = DEFAULT_ALIGNMENT, 
	allocator := context.allocator, 
) -> rawptr {…}

default_resize_bytes_align ¶

default_resize_bytes_align :: proc "odin" (old_data: []u8, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, runtime.Allocator_Error) {…}

delete_cstring ¶

delete_cstring :: proc "odin" (str: cstring, allocator := context.allocator, loc := #caller_location) {…}

delete_dynamic_array ¶

delete_dynamic_array :: proc "odin" (array: $T/[dynamic]$, loc := #caller_location) {…}

delete_map ¶

delete_map :: proc "odin" (m: $T/map[$]$, loc := #caller_location) {…}

delete_slice ¶

delete_slice :: proc "odin" (array: $T/[]$, allocator := context.allocator, loc := #caller_location) {…}

delete_string ¶

delete_string :: proc "odin" (str: string, allocator := context.allocator, loc := #caller_location) {…}

dynamic_pool_alloc ¶

dynamic_pool_alloc :: proc "odin" (pool: ^Dynamic_Pool, bytes: int) -> rawptr {…}

dynamic_pool_alloc_bytes ¶

dynamic_pool_alloc_bytes :: proc "odin" (pool: ^Dynamic_Pool, bytes: int) -> ([]u8, runtime.Allocator_Error) {…}

dynamic_pool_allocator ¶

dynamic_pool_allocator :: proc "odin" (pool: ^Dynamic_Pool) -> runtime.Allocator {…}

dynamic_pool_allocator_proc ¶

dynamic_pool_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

dynamic_pool_destroy ¶

dynamic_pool_destroy :: proc "odin" (pool: ^Dynamic_Pool) {…}

dynamic_pool_free_all ¶

dynamic_pool_free_all :: proc "odin" (pool: ^Dynamic_Pool) {…}

dynamic_pool_init ¶

dynamic_pool_init :: proc "odin" (
	pool:            ^Dynamic_Pool, 
	block_allocator := context.allocator, 
	array_allocator := context.allocator, 
	block_size:      int = DYNAMIC_POOL_BLOCK_SIZE_DEFAULT, 
	out_band_size:   int = DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT, 
) {…}

dynamic_pool_reset ¶

dynamic_pool_reset :: proc "odin" (pool: ^Dynamic_Pool) {…}

end_arena_temp_memory ¶

end_arena_temp_memory :: proc "odin" (using tmp: Arena_Temp_Memory) {…}

free ¶

free :: proc "odin" (ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}

free_all ¶

free_all :: proc "odin" (allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}

free_bytes ¶

free_bytes :: proc "odin" (bytes: []u8, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}

init_arena ¶

init_arena :: proc "odin" (a: ^Arena, data: []u8) {…}

init_small_stack ¶

init_small_stack :: proc "odin" (s: ^Small_Stack, data: []u8) {…}

init_stack ¶

init_stack :: proc "odin" (s: ^Stack, data: []u8) {…}

is_power_of_two ¶

is_power_of_two :: proc "contextless" (x: uintptr) -> bool {…}

make_aligned ¶

make_aligned :: proc "odin" ($T: typeid/[]$, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: runtime.Allocator_Error) {…}

make_any ¶

make_any :: proc "contextless" (data: rawptr, id: typeid) -> any {…}

make_dynamic_array ¶

make_dynamic_array :: proc "odin" ($T: typeid/[dynamic]$, allocator := context.allocator, loc := #caller_location) -> (T, runtime.Allocator_Error) {…}

make_dynamic_array_len ¶

make_dynamic_array_len :: proc "odin" ($T: typeid/[dynamic]$, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, runtime.Allocator_Error) {…}

make_dynamic_array_len_cap ¶

make_dynamic_array_len_cap :: proc "odin" ($T: typeid/[dynamic]$, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: runtime.Allocator_Error) {…}

make_fixed_byte_buffer ¶

make_fixed_byte_buffer :: proc "contextless" (backing: []u8) -> Fixed_Byte_Buffer {…}

make_map ¶

make_map :: proc "odin" ($T: typeid/map[$]$, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {…}

make_multi_pointer ¶

make_multi_pointer :: proc "odin" ($T: typeid/[^]$, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: $/[^]$, err: runtime.Allocator_Error) {…}

make_slice ¶

make_slice :: proc "odin" ($T: typeid/[]$, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, runtime.Allocator_Error) {…}

new ¶

new :: proc "odin" ($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^typeid, runtime.Allocator_Error) {…}

new_aligned ¶

new_aligned :: proc "odin" ($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^typeid, err: runtime.Allocator_Error) {…}

new_clone ¶

new_clone :: proc "odin" (data: $, allocator := context.allocator, loc := #caller_location) -> (t: ^$, err: runtime.Allocator_Error) {…}

nil_allocator ¶

nil_allocator :: proc "odin" () -> runtime.Allocator {…}

nil_allocator_proc ¶

nil_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

panic_allocator ¶

panic_allocator :: proc "odin" () -> runtime.Allocator {…}

panic_allocator_proc ¶

panic_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

ptr_offset ¶

ptr_offset :: intrinsics.ptr_offset

ptr_sub ¶

ptr_sub :: intrinsics.ptr_sub

ptr_to_bytes ¶

ptr_to_bytes :: proc "contextless" (ptr: ^$, len: int) -> []u8 {…}

query_features ¶

query_features :: proc "odin" (allocator := context.allocator, loc := #caller_location) -> (set: runtime.Allocator_Mode_Set) {…}

query_info ¶

query_info :: proc "odin" (pointer: rawptr, allocator: runtime.Allocator, loc := #caller_location) -> (props: runtime.Allocator_Query_Info) {…}

reinterpret_copy ¶

reinterpret_copy :: proc "contextless" ($T: typeid, ptr: rawptr) -> (value: typeid) {…}

resize ¶

resize :: proc "odin" (
	ptr:                rawptr, 
	old_size, new_size: int, 
	alignment:          int = DEFAULT_ALIGNMENT, 
	allocator := context.allocator, 
) -> rawptr {…}

resize_bytes ¶

resize_bytes :: proc "odin" (old_data: []u8, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, runtime.Allocator_Error) {…}

scratch_allocator ¶

scratch_allocator :: proc "odin" (allocator: ^Scratch_Allocator) -> runtime.Allocator {…}

scratch_allocator_destroy ¶

scratch_allocator_destroy :: proc "odin" (s: ^Scratch_Allocator) {…}

scratch_allocator_init ¶

scratch_allocator_init :: proc "odin" (s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) -> runtime.Allocator_Error {…}

scratch_allocator_proc ¶

scratch_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

set ¶

set :: proc "contextless" (data: rawptr, value: u8, len: int) -> rawptr {…}

simple_equal ¶

simple_equal :: proc "contextless" (a, b: $) -> bool {…}

slice_data_cast ¶

slice_data_cast :: proc "contextless" ($T: typeid/[]$, slice: T) -> T {…}

slice_ptr ¶

slice_ptr :: proc "contextless" (ptr: ^$, len: int) -> []$ {…}

slice_to_bytes ¶

slice_to_bytes :: proc "contextless" (slice: $T/[]$) -> []u8 {…}

slice_to_components ¶

slice_to_components :: proc "contextless" (slice: $T/[]$) -> (data: ^$, len: int) {…}

small_stack_allocator ¶

small_stack_allocator :: proc "odin" (stack: ^Small_Stack) -> runtime.Allocator {…}

small_stack_allocator_proc ¶

small_stack_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

small_stack_init ¶

small_stack_init :: proc "odin" (s: ^Small_Stack, data: []u8) {…}

stack_allocator ¶

stack_allocator :: proc "odin" (stack: ^Stack) -> runtime.Allocator {…}

stack_allocator_proc ¶

stack_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

stack_init ¶

stack_init :: proc "odin" (s: ^Stack, data: []u8) {…}

tracking_allocator ¶

tracking_allocator :: proc "odin" (data: ^Tracking_Allocator) -> runtime.Allocator {…}

tracking_allocator_destroy ¶

tracking_allocator_destroy :: proc "odin" (t: ^Tracking_Allocator) {…}

tracking_allocator_init ¶

tracking_allocator_init :: proc "odin" (t: ^Tracking_Allocator, backing_allocator: runtime.Allocator, internals_allocator := context.allocator) {…}

tracking_allocator_proc ¶

tracking_allocator_proc :: proc "odin" (
	allocator_data:  rawptr, 
	mode:            runtime.Allocator_Mode, 
	size, alignment: int, 
	old_memory:      rawptr, 
	old_size:        int, 
) -> ([]u8, runtime.Allocator_Error) {…}

zero ¶

zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {…}

zero_explicit ¶

zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr {…}

zero_item ¶

zero_item :: proc "contextless" (item: $P/^$) -> $P/^$ {…}

zero_slice ¶

zero_slice :: proc "contextless" (data: $T/[]$) -> $T/[]$ {…}

Procedure Groups

raw_data ¶

raw_data :: proc{
	runtime.raw_array_data,
	runtime.raw_slice_data,
	runtime.raw_dynamic_array_data,
	runtime.raw_string_data,
	runtime.raw_simd_data,
}

Source Files

Generation Information

Generated with odin version dev-2022-10 (vendor "odin") Windows_amd64 @ 2022-10-05 21:11:47.461170900 +0000 UTC