In my development, which makes extensive use of opaque data types to foster an OO-like approach, I too wrestled with this question. At first, I was decidedly in the camp of eliminating the destructor from the YAGNI perspective, as well as the MISRA "dead code" perspective. (I had plenty of resource room, that wasn't a consideration.)
However... the lack of a destructor can make testing more difficult, as in automated unit/integration testing. Conventionally, each test should support a setup/teardown so that objects can be created, manipulated, then destroyed. They are destroyed in order to assure a clean, untainted starting point for thenext test. To do this, the class needs a destructor.
Therefore, in my experience, the "aint't" in YAGNI turns out be to an "are" and I ended up creating destructors for every class whether I thought I'd need it or not. Even if I skipped testing, at least a correctly designed destructor exists for the poor slob that follows me will have one. (And, to a much lesser value, it makes the code more reusable in that it can be used in an environment where it would be destroyed.)
While that addresses YAGNI, it does not address dead code. For that, I find that a conditional compile macro something like #define BUILD_FOR_TESTING allows the destructor to be eliminated from the final production build.
Doing it this way: you have destructor for testing/future reuse, and you satisfy the design objectives of YAGNI and "no dead code" rules.