compare_exchange_weak导致coredump

在学习C++多并发的时候模拟写栈时,当使用下面的pop函数时,偶发性导致coredump,但是我理解中的compare_exchange_weak将设定值给当前值时只在当前值与期望值相同的情况下,请问这个coredump触发因是因为哪里导致的哈

template<typename T>
class mystack
{
    struct node
    {
        std::shared_ptr<T> data;  // 1 指针获取数据
        node* next = nullptr;

        node(T const& data_):
            data(std::make_shared<T>(data_))  // 2 让std::shared_ptr指向新分配出来的T
        {
            next = nullptr;
        }
    };

    std::atomic<int>    threads_in_pop;
    std::atomic<node*>  head;

    std::atomic<node*>  need_clear_list;
    
    void clear_all_need_list(node *clear_node)
    {
        while(clear_node)
        {
            node *temp_node = clear_node ->next;
            delete clear_node;
            clear_node = temp_node;
        }
    }

    void chain_pending_nodes(node *nodes)
    {
        if(!nodes)
        {
            return;
        }
        node *last = nodes;
        while(node *next = last->next)
        {
            std::cout<<"find next"<<std::endl;
            last = next;
        }
        chain_pending_nodes(nodes,last);
    }

    void chain_pending_nodes(node *first,node *last)
    {
        last->next = need_clear_list.load();
        while(!need_clear_list.compare_exchange_weak(last->next,first));
    }

    void chain_pending_node(node *nodes)
    {
        chain_pending_nodes(nodes,nodes);
    }

    void clear_pop_threads(node *clear_data)
    {
        if(threads_in_pop == 1)
        {
            node *old_head = need_clear_list.exchange(nullptr);
            if(threads_in_pop.fetch_sub(1) == 1)
            {
                clear_all_need_list(old_head);
            }
            else 
            {
                chain_pending_nodes(old_head);
            }
            delete clear_data;
        }
        else 
        {
            // clear_data ->next = nullptr;
            // chain_pending_nodes(clear_data);            //理论上与上方的一致
            chain_pending_node(clear_data);

            threads_in_pop.fetch_sub(1);
            std::cout<<"threads_in_pop != 1"<<std::endl;
        }
    }

    public:
        mystack()
        {
            threads_in_pop = 0;
            need_clear_list.store(nullptr);
            std::cout<<"create id:"<<std::this_thread::get_id()<<std::endl;
            head.store(nullptr);   //如果不设置初值,head将不一定为nullptr
        }
        ~mystack()
        {
            std::cout<<"~id:"<<std::this_thread::get_id()<<std::endl;
        }
        void push(T const new_data)
        {
            node *newnode = new node(new_data);
            newnode->next = head.load();
            while(!head.compare_exchange_weak(newnode->next,newnode));
        }

        std::shared_ptr<T> pop()
        {
            threads_in_pop.fetch_add(1);
            node *oldnode = head.load();
            while( oldnode && !head.compare_exchange_weak(oldnode,oldnode->next,std::memory_order_release,std::memory_order_relaxed));

            std::shared_ptr<T> res;
            if(oldnode)
            {
                res.swap(oldnode->data);
                delete oldnode;   //将会导致coredump
            }
            
            // clear_pop_threads(oldnode);

            return res;
        }
};