Many microcontroller only have a stack so you just can't use heap .
Also @Varriount, @Udiknedormin today you can do:
type
SharedArray[T] = object
dataRef: ref[ptr T]
data*: ptr UncheckedArray[T]
len*: int
proc deallocSharedArray[T](dataRef: ref[ptr T]) =
if not dataRef[].isNil:
deallocShared(dataRef[])
dataRef[] = nil
proc newSharedArray[T](size: int): SharedArray[T] =
# Note the finalizer to call the GC when needed
new(result.dataRef, deallocSharedArray)
# Note the shared memory allocation
let address = cast[ByteAddress](allocShared0(sizeof(T) * size))
result.dataRef[] = cast[ptr T](address)
result.data = cast[ptr UncheckedArray[T]](address)
result.len = size
proc `[]`[T](a: SharedArray[T], idx: int): T =
assert idx >= 0 and idx < a.len # bounds-checking
a.data[idx]
proc `[]`[T](a: var SharedArray[T], idx: int): var T =
assert idx >= 0 and idx < a.len # bounds-checking
a.data[idx]
proc `[]=`[T](a: var SharedArray[T], idx: int, v: T) =
assert idx >= 0 and idx < a.len # bounds-checking
a.data[idx] = v
var a = newSharedArray[int](5)
a[3] = 10
echo a[0] # 0
echo a[3] # 10