### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current behaviour

The `bitcoind -dbcache=100 -par=4 -disablewallet -reindex-chainstate` command fails with OOM. First reported in https://github.com/bitcoin/bitcoin/issues/28718#issuecomment-1807197107.

### Expected behaviour

RAM usage does not exceed 0.9 GB.

### Steps to reproduce

100% reproducibility with Guix compiled binaries.

### Relevant log output

```
2023-11-17T18:43:31Z [loadblk] UpdateTip: new best=000000000000000016d35e6ca77dea6f4e2caa387f245a712b1df5bbab3c559c height=314541 version=0x00000002 log2_work=80.091273 tx=44112815 date='2014-08-08T11:42:41Z' progress=0.049410 cache=105.6MiB(13710725txo)
```

### How did you obtain Bitcoin Core

Compiled from source

### What version of Bitcoin Core are you using?

master@5aa0c82ccd6ceb4a141686fc8658f679de75a787

### Operating system and version

Armbian 23.8.3 jammy, 1 GB swap-file

### Machine specifications

armv7l, 8 cores, 2 GB RAM
{
        if (IsFreeListUsable(bytes, alignment)) {
            const std::size_t num_alignments = NumElemAlignBytes(bytes);
            if (nullptr != m_free_lists[num_alignments]) {
                // we've already got data in the pool's freelist, unlink one element and return the pointer
                // to the unlinked memory. Since FreeList is trivially destructible we can just treat it as
                // uninitialized memory.
                return std::exchange(m_free_lists[num_alignments], m_free_lists[num_alignments]->m_next);
            }
            // freelist is empty: get one allocation from allocated chunk memory.
            const std::ptrdiff_t round_bytes = static_cast<std::ptrdiff_t>(num_alignments * ELEM_ALIGN_BYTES);
            if (round_bytes > m_available_memory_end - m_available_memory_it) {
                
                AllocateChunk();
            }
            // Make sure we use the right amount of bytes for that freelist (might be rounded up),
            return std::exchange(m_available_memory_it, m_available_memory_it + round_bytes);
        }
        // Can't use the pool => use operator new()
        return ::operator new (bytes, std::align_val_t{alignment});
    }
    /**
     * Returns a block to the freelists, or deletes the block when it did not come from the chunks.
     */
    void Deallocate(void* p, std::size_t bytes, std::size_t alignment) noexcept