only call alloc/free once