the nil allocator
This is an idea introduced to me by the Odin programming language: a custom allocator where allocations only return NULL, where deallocations only assert that the provided pointer was NULL, etc.
global NilAllocator = @record{}
global nilallocator: NilAllocator
function NilAllocator:alloc(size: usize, flags: facultative(usize)): pointer <inline>
return nilptr
end
function NilAllocator:alloc0(size: usize, flags: facultative(usize)): pointer <inline>
return nilptr
end
function NilAllocator:dealloc(p: pointer): void <inline>
assert(p == nilptr)
end
function NilAllocator:realloc(p: pointer, newsize: usize, oldsize: usize): pointer <inline>
assert(p == nilptr)
return nilptr
end
require 'allocators.allocator'
## Allocator_implement_interface(NilAllocator)
return NilAllocatonAnd to demonstrate it, a program that panics with an Out of memory error:
require 'nilallocator' global embedded_general_allocator = nilallocator require 'allocators.default' -- defers to previous global if present require 'string' local s1 = 'a' .. 'b' print(s1)
or more roughly,
require 'nilallocator' require 'allocators.default' ## context.rootscope.symbols.default_allocator = nilallocator ## context.rootscope.symbols.DefaultAllocator = NilAllocator require 'string' local s1 = 'a' .. 'b' print(s1)
Note the Lua to change both the type and value of default_allocator, and note: those lines will silently do little useful without the require 'allocators.default' line, to give them something to change. Although there are no panics in the explicit implementation of NilAllocator, the string-concat code that's loaded calls xalloc, which panics if allocation fails.
Note also: this kind of Lua-overwriting isn't the same thing as setting a global. The following program doesn't panic:
require 'nilallocator' require 'allocators.default' require 'string' local s1 = 'a' .. 'b' print(s1) ## context.rootscope.symbols.default_allocator = nilallocator ## context.rootscope.symbols.DefaultAllocator = NilAllocator local s2 = 'c' .. 'd' print(s2)