Lua Notes

the nil allocator
Login

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 NilAllocaton

And 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)