I'm looking at RT_FREE_RECURSE again (only used for DSA memory), and I'm not convinced it's freeing all the memory. It's been many months since we discussed this last, but IIRC we cannot just tell DSA to free all its segments, right? Is there currently anything preventing us from destroying the whole DSA area at once?
+ /* The last level node has pointers to values */ + if (shift == 0) + { + dsa_free(tree->dsa, ptr); + return; + } IIUC, this doesn't actually free leaves, it only frees the last-level node. And, this function is unaware of whether children could be embedded values. I'm thinking we need to get rid of the above pre-check and instead, each node kind to have something like (e.g. node4): RT_PTR_ALLOC child = n4->children[i]; if (shift > 0) RT_FREE_RECURSE(tree, child, shift - RT_SPAN); else if (!RT_CHILDPTR_IS_VALUE(child)) dsa_free(tree->dsa, child); ...or am I missing something?