UB или не UB в конструкторе с атомиком

Есть у меня конструктор, но случилось раз такое... что компилился 100% краш на nullptr.

class sStaticUnorderedMap final
{
public:
    sStaticUnorderedMap(std::atomic_bool& _isAvaiable, spin_lock& _spinLock) : isAvaiable(_isAvaiable),
                                                                                spinLock(_spinLock)
    {
        spinLock.lock();
        _size = 0;
        memset(data, 0, MAX_N * (sizeof(T) + sizeof(K) + sizeof(H) + sizeof(B)));
        for (int i = 0; i < MAX_N; i++)
        {
            *(reinterpret_cast<B*>(data + i * BLOCK_SZ + OFFSET_B)) = 0;
        }
        isAvaiable = true; // КРАШ ТУТ
        spinLock.unlock();
    }
    //...

    std::atomic_bool& isAvaiable;
    spin_lock& spinLock;
}


std::atomic_bool memory_located_is(false);
spin_lock memory_located_lock;
sStaticUnorderedMap<uint64_t, uint64_t, 3000000> memory_located(memory_located_is, memory_located_lock);

Крашилось от того, что инициализация атомика ещё не произошла и был nullptr access. UB или MSVC решил, что слишком легко мне программируется? Кто виноват и что делать?

Весь код:

constexpr bool is_s_memory = false;

template <class K, class T, int MAX_N = 128>
class sStaticUnorderedMap final
{
public:
    using B = std::size_t;
    using H = std::size_t;
    using S = std::size_t;
    using value_type = std::pair<const K, T>;

    static const S OFFSET_B = 0;
    static const S OFFSET_H = sizeof(B);
    static const S OFFSET_K = sizeof(B) + sizeof(H);
    static const S OFFSET_T = sizeof(B) + sizeof(H) + sizeof(K);
    static const S BLOCK_SZ = sizeof(B) + sizeof(H) + sizeof(K) + sizeof(T);

    static const S S_NOTFOUND = -1;

    sStaticUnorderedMap(std::atomic_bool& _isAvaiable, spin_lock& _spinLock) : isAvaiable(_isAvaiable),
                                                                                spinLock(_spinLock)
    {
        spinLock.lock();
        _size = 0;
        memset(data, 0, MAX_N * (sizeof(T) + sizeof(K) + sizeof(H) + sizeof(B)));
        for (int i = 0; i < MAX_N; i++)
        {
            *(reinterpret_cast<B*>(data + i * BLOCK_SZ + OFFSET_B)) = 0;
        }
        isAvaiable = true;
        spinLock.unlock();
    }

    ~sStaticUnorderedMap()
    {
        spinLock.lock();
        isAvaiable = false;
        for (int i = 0; i < MAX_N; i++)
        {
            if (*(reinterpret_cast<B*>(data + i * BLOCK_SZ + OFFSET_B)) == 1)
            {
                K& tableK = *(reinterpret_cast<K*>(data + i * BLOCK_SZ + OFFSET_K));
                T& tableT = *(reinterpret_cast<T*>(data + i * BLOCK_SZ + OFFSET_T));
                tableK.~K();
                tableT.~T();
                *(reinterpret_cast<B*>(data + i * BLOCK_SZ + OFFSET_B)) = 0;
            }
        }
        _size = 0;
        spinLock.unlock();
    }

    void insert(const K& k, const T& t)
    {
        insert(K(k), T(t));
    }

    void insert(K&& k, T&& t)
    {
        _size++;
        if (_size >= MAX_N)
            throw;

        H hash = std::hash<K>()(k);
        S pos = hash % MAX_N;

        while (true)
        {
            if (*(reinterpret_cast<B*>(data + pos * BLOCK_SZ + OFFSET_B)) == 0)
            {
                *(reinterpret_cast<B*>(data + pos * BLOCK_SZ + OFFSET_B)) = 1;
                *(reinterpret_cast<H*>(data + pos * BLOCK_SZ + OFFSET_H)) = hash;
                new(reinterpret_cast<K*>(data + pos * BLOCK_SZ + OFFSET_K)) K(k);
                new(reinterpret_cast<T*>(data + pos * BLOCK_SZ + OFFSET_T)) T(t);
                return;
            }
            const H& tableH = *(reinterpret_cast<H*>(data + pos * BLOCK_SZ + OFFSET_H));
            if (hash == tableH)
            {
                const K& tableK = *(reinterpret_cast<K*>(data + pos * BLOCK_SZ + OFFSET_K));
                if (tableK == k)
                {
                    T& tableT = *(reinterpret_cast<T*>(data + pos * BLOCK_SZ + OFFSET_T));
                    tableT = t;
                }
            }

            pos = (pos + 1) % MAX_N;
        }
    }

    S find(const K& k)
    {
        H hash = std::hash<K>()(k);
        S pos = hash % MAX_N;

        while (true)
        {
            if (*(reinterpret_cast<B*>(data + pos * BLOCK_SZ + OFFSET_B)) == 0)
            {
                return S_NOTFOUND;
            }
            const H& tableH = *(reinterpret_cast<H*>(data + pos * BLOCK_SZ + OFFSET_H));
            if (hash == tableH)
            {
                const K& tableK = *(reinterpret_cast<K*>(data + pos * BLOCK_SZ + OFFSET_K));
                if (tableK == k)
                {
                    return pos;
                }
            }

            pos = (pos + 1) % MAX_N;
        }
    }

    bool posIsLess(S posDel, S s, S hashPos)
    {
        if (s < posDel)
        {
            return (hashPos > s) & (hashPos <= posDel);
        }
        return (hashPos > s) | (hashPos <= posDel);
    }

    B& linkPosB(S pos)
    {
        return *(reinterpret_cast<B*>(data + pos * BLOCK_SZ + OFFSET_B));
    }

    H& linkPosH(S pos)
    {
        return *(reinterpret_cast<H*>(data + pos * BLOCK_SZ + OFFSET_H));
    }

    K& linkPosK(S pos)
    {
        return *(reinterpret_cast<K*>(data + pos * BLOCK_SZ + OFFSET_K));
    }

    T& linkPosT(S pos)
    {
        return *(reinterpret_cast<T*>(data + pos * BLOCK_SZ + OFFSET_T));
    }

    void posErase_no_rec(S s)
    {
        S posDel = s;
        while (true)
        {
            s = (s + 1) % MAX_N;
            //End line elems
            if (!linkPosB(s))
            {
                linkPosK(posDel).~K();
                linkPosT(posDel).~T();
                linkPosB(posDel) = 0;
                return;
            }

            S hashPos = linkPosH(s) % MAX_N;
            if (posIsLess(posDel, s, hashPos))
            {
                linkPosH(posDel) = std::move(linkPosH(s));
                linkPosK(posDel) = std::move(linkPosK(s));
                linkPosT(posDel) = std::move(linkPosT(s));
                posDel = s;
            }
        }
    }

    bool erase(const K& k)
    {
        S posDel = find(k);
        H hash = std::hash<K>()(k);
        if (posDel == S_NOTFOUND)
        {
            return false;
        }
        S posMov = S_NOTFOUND;
        S pos = (posDel + 1) % MAX_N;

        while (true)
        {
            if (*(reinterpret_cast<B*>(data + pos * BLOCK_SZ + OFFSET_B)) == 0)
            {
                if (posMov != S_NOTFOUND)
                {
                    K& tableMovK = *(reinterpret_cast<K*>(data + posMov * BLOCK_SZ + OFFSET_K));
                    T& tableMovT = *(reinterpret_cast<T*>(data + posMov * BLOCK_SZ + OFFSET_T));
                    B& tableMovB = *(reinterpret_cast<B*>(data + posMov * BLOCK_SZ + OFFSET_B));

                    K& tableK = *(reinterpret_cast<K*>(data + posDel * BLOCK_SZ + OFFSET_K));
                    T& tableT = *(reinterpret_cast<T*>(data + posDel * BLOCK_SZ + OFFSET_T));

                    tableK = std::move(tableMovK);
                    tableT = std::move(tableMovT);

                    posErase_no_rec(posMov);
                }
                else
                {
                    //Simple single thing
                    K& tableK = *(reinterpret_cast<K*>(data + posDel * BLOCK_SZ + OFFSET_K));
                    T& tableT = *(reinterpret_cast<T*>(data + posDel * BLOCK_SZ + OFFSET_T));
                    B& tableB = *(reinterpret_cast<B*>(data + posDel * BLOCK_SZ + OFFSET_B));

                    posErase_no_rec(posDel);
                }
                _size--;
                return true;
            }
            const H& tableH = *(reinterpret_cast<H*>(data + pos * BLOCK_SZ + OFFSET_H));
            if (hash == tableH)
            {
                const K& tableK = *(reinterpret_cast<K*>(data + pos * BLOCK_SZ + OFFSET_K));
                if (tableK == k)
                {
                    posMov = pos;
                }
            }
            pos = (pos + 1) % MAX_N;
        }
    }

    std::string strCC(std::string s)
    {
        std::string res;
        for (int i = 0; i < 4; i++)
        {
            if (i < s.size())
            {
                res += s[i];
            }
            else
            {
                res += ' ';
            }
        }
        return res;
    }

    std::string to_str()
    {
        std::string str;
        for (int i = 0; i < MAX_N; i++)
        {
            if (*(reinterpret_cast<B*>(data + i * BLOCK_SZ + OFFSET_B)) == 1)
            {
                const H& tableH = *(reinterpret_cast<H*>(data + i * BLOCK_SZ + OFFSET_H));
                const K& tableK = *(reinterpret_cast<K*>(data + i * BLOCK_SZ + OFFSET_K));
                const T& tableT = *(reinterpret_cast<T*>(data + i * BLOCK_SZ + OFFSET_T));
                str += strCC(std::to_string(tableH % MAX_N));
            }
            else
            {
                str += "    ";
            }
            str += "|";
        }
        return str;
    }

    S size()
    {
        return _size;
    }

    char data[MAX_N * (sizeof(T) + sizeof(K) + sizeof(H) + sizeof(B))];
    S _size;
    std::atomic_bool& isAvaiable;
    spin_lock& spinLock;
};


std::atomic_bool memory_located_is(false);
spin_lock memory_located_lock;
sStaticUnorderedMap<uint64_t, uint64_t, 3000000> memory_located(memory_located_is, memory_located_lock);

//Wery dangerous code

void* operator new(std::size_t sz)
{
    void* ptr = std::malloc(sz);
    if (ptr)
    {
        if constexpr (is_s_memory)
        {
            memory_located_lock.lock();
            //if (memory_located.size() > 40000) {
            //  std::puts("M");
            //}
            if (memory_located_is)
                memory_located.insert(reinterpret_cast<uint64_t>(ptr), static_cast<uint64_t>(sz));
            memory_located_lock.unlock();
        }
        return ptr;
    }
    throw;
}

void operator delete(void* ptr) noexcept
{
    if constexpr (is_s_memory)
    {
        memory_located_lock.lock();
        if (memory_located_is)
            memory_located.erase(reinterpret_cast<uint64_t>(ptr));
        memory_located_lock.unlock();
    }
    std::free(ptr);
}


std::unordered_map<uint64_t, uint64_t> getTable()
{
    unordered_map<uint64_t, uint64_t> res;

    using StaticTable = sStaticUnorderedMap<uint64_t, uint64_t, 3000000>;

    std::atomic_bool memory_located_copy_is(false);
    spin_lock memory_located_copy_lock;
    StaticTable* pmemory_located_copy = new StaticTable(memory_located_copy_is, memory_located_copy_lock);


    memory_located_lock.lock();
    if (memory_located_is)
    {
        memcpy(&pmemory_located_copy->data, memory_located.data, sizeof(memory_located.data) * sizeof(char));
        pmemory_located_copy->_size = memory_located._size;
    }
    memory_located_lock.unlock();

    if (memory_located_is)
    {
        for (int i = 0; i < 3000000; i++)
        {
            if (*(reinterpret_cast<StaticTable::B*>(pmemory_located_copy->data + i * StaticTable::BLOCK_SZ + StaticTable
                ::OFFSET_B)) == 1)
            {
                const StaticTable::H& tableH = *(reinterpret_cast<StaticTable::H*>(pmemory_located_copy->data + i *
                    StaticTable::BLOCK_SZ + StaticTable::OFFSET_H));
                uint64_t tableK = *(reinterpret_cast<uint64_t*>(pmemory_located_copy->data + i * StaticTable::BLOCK_SZ +
                    StaticTable::OFFSET_K));
                uint64_t tableT = *(reinterpret_cast<uint64_t*>(pmemory_located_copy->data + i * StaticTable::BLOCK_SZ +
                    StaticTable::OFFSET_T));
                res.insert({tableK, tableT});
            }
        }
    }

    delete pmemory_located_copy;
    pmemory_located_copy = nullptr;

    return res;
}

Ответы (0 шт):