Myself, I'd lean towards a sound (linear) type theory. If it's not too much trouble, insert the run-time checks in debug builds but use the type system to erase them for optimized builds. It might seem like the mountain is impossible to climb if you're not used to formalizing such systems but every mountain is surmounted one step at a time.
It's hard to bolt-on correctness after the fact. In my experience, for critical pieces like this, it's better to get the specification right first before digging in too deep and writing code.
Best of luck on the project either way you go. Memory safety is increasingly important!