Author of Botan replied to me that
The problem is the globally defined object.
The problem is that the mlock pool is a singleton created on first use then destroyed sometime after main returns. First your object is created. It allocates memory. This results in the pool being created. Destruction happens LIFO. So first the pool is destroyed. Then your object is destroyed, and attempts to touch memory (to zero it) which has already been unmapped.
Workarounds,
- Create a Botan::Allocator_Initializer object to force initialization
before your object is created (thus the pool lives until after your
object has been destructed) - Disable locking_allocator module
- Set env var BOTAN_MLOCK_POOL_SIZE to 0
- No global vars
In principle the locking allocator instead of munmaping the memory, just zeros it, and leave it to be unmapped by the OS on process exit. This might still break invariants, but not as badly. It also causes valgrind to reports leaks which is obnoxious.
I think because it was mmap’ed directly and not through malloc, valgrind doesn’t track it.