### 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
static_assert((MAX_BLOCK_SIZE_BYTES & (ELEM_ALIGN_BYTES - 1)) == 0, "MAX_BLOCK_SIZE_BYTES needs to be a multiple of the alignment.");
    /**
     * Size in bytes to allocate per chunk
     */
    const size_t m_chunk_size_bytes;
    /**
     * Contains all allocated pools of memory, used to free the data in the destructor.
     */
    std::list<std::byte*> m_allocated_chunks{};
    /**
     * Single linked lists of all data that came from deallocating.
     * m_free_lists[n] will serve blocks of size n*ELEM_ALIGN_BYTES.
     */
    std::array<ListNode*, MAX_BLOCK_SIZE_BYTES / ELEM_ALIGN_BYTES + 1> m_free_lists{};
    /**
     * Points to the beginning 
     */
    std::byte* m_available_memory_it = nullptr;
    /**
     * Points to the end 
     *
     * That member variable is redundant, and is always equal to `m_allocated_chunks.back() + m_chunk_size_bytes`
     * whenever it is accessed, but `m_available_memory_end` caches this for clarity and efficiency.
     */
    std::byte* m_available_memory_end = nullptr;
    /**
     * How many  index
     * into m_free_lists. Round up for the special case when bytes==0.
     */
    [[nodiscard]] static constexpr std::size_t NumElemAlignBytes(std::size_t bytes)