You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双向循环链表内存访问错误求助(SFML菜单开发场景)

问题根源

  1. 浅拷贝引发的双重析构/野指针访问:CDblLinkedList未实现拷贝构造与赋值运算符重载,默认的浅拷贝会让多个链表对象共享节点资源。当CSubMenu被拷贝到链表节点时,若CSubMenu内部也包含CDblLinkedList,两个CSubMenu实例会共享同一份链表数据,析构时会重复释放或访问已失效的指针。
  2. 不必要的对象拷贝:Insert函数使用值传递参数,导致CSubMenu对象被强制拷贝,放大了浅拷贝的危害。
  3. CNode构造的冗余拷贝:CNode的构造函数同样使用值传递,会额外拷贝T类型对象。

修复步骤

1. 禁用CDblLinkedList的拷贝操作(若无需拷贝链表)

在CDblLinkedList类的私有成员中添加,禁止默认拷贝构造与赋值:

template<typename T>
class CDblLinkedList{
private:
    CNode<T>*head=nullptr,*current=nullptr;
    // 禁用拷贝构造与赋值运算符
    CDblLinkedList(const CDblLinkedList&) = delete;
    CDblLinkedList& operator=(const CDblLinkedList&) = delete;
public:
    // ... 原有成员
};

2. 修改Insert与CNode构造为引用传递,避免冗余拷贝

修改CNode的构造函数为const左值引用:

// CNode.h
template <typename T>
class CNode{
public:
    // 修改构造函数参数为const引用
    CNode(const T& p_data);
    // ... 原有成员
};

template <typename T>
CNode<T>::CNode(const T& p_data):data(p_data){}

修改CDblLinkedList的Insert函数为const引用参数:

// CDblLinkedList.h
template<typename T>
void CDblLinkedList<T>::Insert(const T& p_data){
    CNode<T> * dummy=new CNode<T>(p_data);
    // ... 原有逻辑不变
}

3. 调整CSubMenu的拷贝策略

如果CSubMenu无需拷贝,同样禁用它的拷贝构造与赋值运算符:

// CSubMenu.h
class CSubMenu{
private:
    // 禁用拷贝构造与赋值
    CSubMenu(const CSubMenu&) = delete;
    CSubMenu& operator=(const CSubMenu&) = delete;
public:
    // ... 原有成员
};

此时若要将CSubMenu插入链表,需使用移动语义转移所有权:

// main.cpp
list.Insert(std::move(left));

4. 可选:链表存储智能指针避免对象拷贝

若需要保留原CSubMenu对象,可将链表改为存储std::unique_ptr<T>,完全避免对象拷贝:

// 修改CNode为存储unique_ptr
template <typename T>
class CNode{
private:
    CNode<T>*prev=nullptr;
    std::unique_ptr<T> data;
    CNode<T>*next=nullptr;
public:
    CNode(std::unique_ptr<T> p_data):data(std::move(p_data)){}
    // 修改GetData返回T*
    T* GetData(void){return(data.get());};
    // ... 原有成员
};

// 修改Insert函数
template<typename T>
void CDblLinkedList<T>::Insert(std::unique_ptr<T> p_data){
    CNode<T> * dummy=new CNode<T>(std::move(p_data));
    // ... 原有逻辑不变
}

// main.cpp中插入方式改为:
list.Insert(std::make_unique<CSubMenu>(300,450,"AlgoText",font,&window));

验证修复

完成上述修改后,程序运行时不会再出现浅拷贝导致的野指针访问,析构时的内存释放也会正确执行。

内容的提问来源于stack exchange,提问作者RayanYI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 05:35:18