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) defer mem.tracking_allocator_destroy(&track) context.allocator = mem.tracking_allocator(&track) _main() for _, leak in track.allocation_map { fmt.printf("%v leaked %m\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
Types (34)
- Allocator
- Allocator_Error
- Allocator_Mode
- Allocator_Mode_Set
- Allocator_Proc
- Allocator_Query_Info
- Arena
- Arena_Temp_Memory
- Buddy_Allocator
- Buddy_Block
- Dynamic_Pool
- Fixed_Byte_Buffer
- Mutex_Allocator
- Raw_Any
- Raw_Complex128
- Raw_Complex64
- Raw_Cstring
- Raw_Dynamic_Array
- Raw_Map
- Raw_Quaternion128
- Raw_Quaternion128_Vector_Scalar
- Raw_Quaternion256
- Raw_Quaternion256_Vector_Scalar
- Raw_Slice
- Raw_Soa_Pointer
- Raw_String
- Scratch_Allocator
- Small_Stack
- Small_Stack_Allocation_Header
- Stack
- Stack_Allocation_Header
- Tracking_Allocator
- Tracking_Allocator_Bad_Free_Entry
- Tracking_Allocator_Entry
Variables (0)
This section is empty.
Procedures (117)
- align_backward
- align_backward_int
- align_backward_uint
- align_backward_uintptr
- align_formula
- align_forward
- align_forward_int
- align_forward_uint
- align_forward_uintptr
- alloc
- alloc_bytes
- alloc_bytes_non_zeroed
- any_to_bytes
- arena_allocator
- arena_allocator_proc
- arena_init
- begin_arena_temp_memory
- buddy_allocator
- buddy_allocator_alloc
- buddy_allocator_free
- buddy_allocator_init
- buddy_allocator_proc
- buddy_block_coalescence
- buddy_block_find_best
- buddy_block_next
- buddy_block_size_required
- buddy_block_split
- buffer_from_slice
- byte_slice
- calc_padding_with_header
- check_zero
- check_zero_ptr
- clone_slice
- compare
- compare_byte_ptrs
- compare_ptrs
- context_from_allocator
- copy
- copy_non_overlapping
- default_resize_align
- default_resize_bytes_align
- default_resize_bytes_align_non_zeroed
- delete_cstring
- delete_dynamic_array
- delete_map
- delete_slice
- delete_string
- dynamic_pool_alloc
- dynamic_pool_alloc_bytes
- dynamic_pool_allocator
- dynamic_pool_allocator_proc
- dynamic_pool_destroy
- dynamic_pool_free_all
- dynamic_pool_init
- dynamic_pool_reset
- end_arena_temp_memory
- free
- free_all
- free_bytes
- free_with_size
- init_arena
- init_small_stack
- init_stack
- is_power_of_two
- make_aligned
- make_any
- make_dynamic_array
- make_dynamic_array_len
- make_dynamic_array_len_cap
- make_fixed_byte_buffer
- make_map
- make_multi_pointer
- make_slice
- mutex_allocator
- mutex_allocator_init
- mutex_allocator_proc
- new
- new_aligned
- new_clone
- nil_allocator
- nil_allocator_proc
- panic_allocator
- panic_allocator_proc
- ptr_offset
- ptr_sub
- ptr_to_bytes
- query_features
- query_info
- raw_data
- reinterpret_copy
- resize
- resize_bytes
- scratch_allocator
- scratch_allocator_destroy
- scratch_allocator_init
- scratch_allocator_proc
- set
- simple_equal
- slice_data_cast
- slice_ptr
- slice_to_bytes
- slice_to_components
- small_stack_allocator
- small_stack_allocator_proc
- small_stack_init
- stack_allocator
- stack_allocator_proc
- stack_init
- tracking_allocator
- tracking_allocator_clear
- tracking_allocator_destroy
- tracking_allocator_init
- tracking_allocator_proc
- zero
- zero_explicit
- zero_item
- zero_slice
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 ¶
Related Procedures With Parameters
Buddy_Allocator ¶
Buddy_Allocator :: struct { head: ^Buddy_Block, tail: ^Buddy_Block, alignment: uint, }
Related Procedures With Parameters
Buddy_Block ¶
Related Procedures With Parameters
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, }
Related Procedures With Parameters
Mutex_Allocator ¶
Related Procedures With Parameters
Raw_Cstring ¶
Raw_Cstring :: runtime.Raw_Cstring
Raw_Dynamic_Array ¶
Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array
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, }
Related Procedures With Parameters
Small_Stack ¶
Small_Stack is a stack-like allocator which uses the smallest possible header but at the cost of non-strict memory freeing order
Related Procedures With Parameters
Small_Stack_Allocation_Header ¶
Small_Stack_Allocation_Header :: struct { padding: u8, }
Stack ¶
Stack is a stack-like allocator which has a strict memory freeing order
Related Procedures With Parameters
Tracking_Allocator ¶
Tracking_Allocator :: struct { backing: runtime.Allocator, allocation_map: map[rawptr]Tracking_Allocator_Entry, bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry, mutex: sync.Mutex, clear_on_free_all: bool, }
Related Procedures With Parameters
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, mode: runtime.Allocator_Mode, err: runtime.Allocator_Error, location: runtime.Source_Code_Location, }
Constants
DEFAULT_ALIGNMENT ¶
DEFAULT_ALIGNMENT :: 2 * align_of(rawptr)
DEFAULT_PAGE_SIZE ¶
DEFAULT_PAGE_SIZE :: 64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 else 16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else 4 * 1024
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 :: runtime.Gigabyte
Kilobyte ¶
Kilobyte :: runtime.Kilobyte
Megabyte ¶
Megabyte :: runtime.Megabyte
Petabyte ¶
Petabyte :: runtime.Petabyte
Terabyte ¶
Terabyte :: runtime.Terabyte
Variables
This section is empty.
Procedures
alloc ¶
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, runtime.Allocator_Error) {…}
alloc_bytes ¶
alloc_bytes :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, runtime.Allocator_Error) {…}
alloc_bytes_non_zeroed ¶
alloc_bytes_non_zeroed :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, runtime.Allocator_Error) {…}
arena_allocator_proc ¶
arena_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
begin_arena_temp_memory ¶
begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory {…}
buddy_allocator ¶
buddy_allocator :: proc(b: ^Buddy_Allocator) -> runtime.Allocator {…}
buddy_allocator_alloc ¶
buddy_allocator_alloc :: proc(b: ^Buddy_Allocator, size: uint, zeroed: bool) -> ([]u8, runtime.Allocator_Error) {…}
buddy_allocator_free ¶
buddy_allocator_free :: proc(b: ^Buddy_Allocator, ptr: rawptr) -> runtime.Allocator_Error {…}
buddy_allocator_init ¶
buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []u8, alignment: uint) {…}
buddy_allocator_proc ¶
buddy_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
buddy_block_coalescence ¶
buddy_block_coalescence :: proc(head, tail: ^Buddy_Block) {…}
buddy_block_find_best ¶
buddy_block_find_best :: proc(head, tail: ^Buddy_Block, size: uint) -> ^Buddy_Block {…}
buddy_block_next ¶
buddy_block_next :: proc(block: ^Buddy_Block) -> ^Buddy_Block {…}
buddy_block_size_required ¶
buddy_block_size_required :: proc(b: ^Buddy_Allocator, size: uint) -> uint {…}
buddy_block_split ¶
buddy_block_split :: proc(block: ^Buddy_Block, size: uint) -> ^Buddy_Block {…}
buffer_from_slice ¶
buffer_from_slice :: proc "contextless" (backing: $T/[]$T) -> [dynamic]$T {…}
clone_slice ¶
clone_slice :: proc(slice: $T/[]$T, allocator := context.allocator, loc := #caller_location) -> (new_slice: $T/[]$T) {…}
default_resize_align ¶
default_resize_align :: proc( old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location, ) -> (res: rawptr, err: runtime.Allocator_Error) {…}
default_resize_bytes_align ¶
default_resize_bytes_align :: proc(old_data: []u8, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, runtime.Allocator_Error) {…}
default_resize_bytes_align_non_zeroed ¶
default_resize_bytes_align_non_zeroed :: proc(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(str: cstring, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
delete_dynamic_array ¶
delete_dynamic_array :: proc(array: $T/[dynamic]$T, loc := #caller_location) -> runtime.Allocator_Error {…}
delete_map ¶
delete_map :: proc(m: $T/map[$T]$T, loc := #caller_location) -> runtime.Allocator_Error {…}
delete_slice ¶
delete_slice :: proc(array: $T/[]$T, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
delete_string ¶
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
dynamic_pool_alloc ¶
dynamic_pool_alloc :: proc(pool: ^Dynamic_Pool, bytes: int) -> (rawptr, runtime.Allocator_Error) {…}
dynamic_pool_alloc_bytes ¶
dynamic_pool_alloc_bytes :: proc(p: ^Dynamic_Pool, bytes: int) -> ([]u8, runtime.Allocator_Error) {…}
dynamic_pool_allocator ¶
dynamic_pool_allocator :: proc(pool: ^Dynamic_Pool) -> runtime.Allocator {…}
dynamic_pool_allocator_proc ¶
dynamic_pool_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
dynamic_pool_destroy ¶
dynamic_pool_destroy :: proc(pool: ^Dynamic_Pool) {…}
dynamic_pool_free_all ¶
dynamic_pool_free_all :: proc(p: ^Dynamic_Pool) {…}
dynamic_pool_init ¶
dynamic_pool_init :: proc( 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, alignment: int = 8, ) {…}
dynamic_pool_reset ¶
dynamic_pool_reset :: proc(p: ^Dynamic_Pool) {…}
end_arena_temp_memory ¶
end_arena_temp_memory :: proc(tmp: Arena_Temp_Memory) {…}
free ¶
free :: proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
free_all ¶
free_all :: proc(allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
free_bytes ¶
free_bytes :: proc(bytes: []u8, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
free_with_size ¶
free_with_size :: proc(ptr: rawptr, byte_count: int, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {…}
init_small_stack ¶
init_small_stack :: proc(s: ^Small_Stack, data: []u8) {…}
make_aligned ¶
make_aligned :: proc($T: typeid/[]T, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: runtime.Allocator_Error) {…}
make_dynamic_array ¶
make_dynamic_array :: proc($T: typeid/[dynamic]T, allocator := context.allocator, loc := #caller_location) -> (T, runtime.Allocator_Error) {…}
make_dynamic_array_len ¶
make_dynamic_array_len :: proc($T: typeid/[dynamic]T, #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($T: typeid/[dynamic]T, #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($T: typeid/map[T]T, #any_int cap: int = 1 << runtime.MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: runtime.Allocator_Error) {…}
make_multi_pointer ¶
make_multi_pointer :: proc($T: typeid/[^]T, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: $/[^]T, err: runtime.Allocator_Error) {…}
make_slice ¶
make_slice :: proc($T: typeid/[]T, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, runtime.Allocator_Error) {…}
mutex_allocator ¶
mutex_allocator :: proc(m: ^Mutex_Allocator) -> runtime.Allocator {…}
mutex_allocator_init ¶
mutex_allocator_init :: proc(m: ^Mutex_Allocator, backing_allocator: runtime.Allocator) {…}
mutex_allocator_proc ¶
mutex_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> (result: []u8, err: runtime.Allocator_Error) {…}
new ¶
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^typeid, runtime.Allocator_Error) {…}
new_aligned ¶
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^typeid, err: runtime.Allocator_Error) {…}
new_clone ¶
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^$T, err: runtime.Allocator_Error) {…}
nil_allocator ¶
nil_allocator :: proc() -> runtime.Allocator {…}
nil_allocator_proc ¶
nil_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
panic_allocator ¶
panic_allocator :: proc() -> runtime.Allocator {…}
panic_allocator_proc ¶
panic_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
ptr_offset ¶
ptr_offset :: intrinsics.ptr_offset
ptr_sub ¶
ptr_sub :: intrinsics.ptr_sub
query_features ¶
query_features :: proc(allocator := context.allocator, loc := #caller_location) -> (set: runtime.Allocator_Mode_Set) {…}
query_info ¶
query_info :: proc(pointer: rawptr, allocator: runtime.Allocator, loc := #caller_location) -> (props: runtime.Allocator_Query_Info) {…}
raw_data ¶
raw_data :: builtin.raw_data
resize ¶
resize :: proc( ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location, ) -> (rawptr, runtime.Allocator_Error) {…}
resize_bytes ¶
resize_bytes :: proc(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(allocator: ^Scratch_Allocator) -> runtime.Allocator {…}
scratch_allocator_destroy ¶
scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) {…}
scratch_allocator_init ¶
scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) -> runtime.Allocator_Error {…}
scratch_allocator_proc ¶
scratch_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
simple_equal ¶
simple_equal :: proc "contextless" (a, b: $T) -> bool {…}
slice_data_cast ¶
slice_data_cast :: proc "contextless" ($T: typeid/[]T, slice: T) -> T {…}
slice_ptr ¶
slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []$T {…}
slice_to_bytes ¶
slice_to_bytes :: proc "contextless" (slice: $T/[]$T) -> []u8 {…}
slice_to_components ¶
slice_to_components :: proc "contextless" (slice: $T/[]$T) -> (data: ^$T, len: int) {…}
small_stack_allocator ¶
small_stack_allocator :: proc(stack: ^Small_Stack) -> runtime.Allocator {…}
small_stack_allocator_proc ¶
small_stack_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
small_stack_init ¶
small_stack_init :: proc(s: ^Small_Stack, data: []u8) {…}
stack_allocator_proc ¶
stack_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location, ) -> ([]u8, runtime.Allocator_Error) {…}
tracking_allocator ¶
tracking_allocator :: proc(data: ^Tracking_Allocator) -> runtime.Allocator {…}
tracking_allocator_clear ¶
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {…}
tracking_allocator_destroy ¶
tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) {…}
tracking_allocator_init ¶
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: runtime.Allocator, internals_allocator := context.allocator) {…}
tracking_allocator_proc ¶
tracking_allocator_proc :: proc( allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> (result: []u8, err: runtime.Allocator_Error) {…}
zero_item ¶
zero_item :: proc "contextless" (item: $P/^$T) -> $P/^$T {…}
zero_slice ¶
zero_slice :: proc "contextless" (data: $T/[]$T) -> $T/[]$T {…}
Procedure Groups
delete ¶
delete :: proc{ delete_string, delete_cstring, delete_dynamic_array, delete_slice, delete_map, }
Source Files
Generation Information
Generated with odin version dev-2024-04 (vendor "odin") Windows_amd64 @ 2024-04-26 21:08:58.595155800 +0000 UTC