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

C++编译错误:尝试引用已删除函数及死锁问题求助

问题解决:编译错误与死锁问题

问题描述

编译时出现attempting to reference a deleted function错误,同时调用P类的del函数会触发死锁。

编译错误信息

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\include\xmemory(671): error C2280: 'C::C(const C &)': attempting to reference a deleted function
C:\Users\HARSHA\Desktop\LC\2022\A\C.h(33): note: compiler has generated 'C::C' here
C:\Users\HARSHA\Desktop\LC\2022\A\C.h(33): note: 'C::C(const C &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::thread::thread(const std::thread &)'
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\include\thread(93): note: 'std::thread::thread(const std::thread &)': function was explicitly deleted

编译错误解决

错误原因

  1. C类拷贝构造被删除:C类包含std::thread成员,std::thread的拷贝构造函数是显式删除的,因此编译器自动删除了C类的隐式拷贝构造函数,代码中潜在的拷贝操作触发了错误。
  2. 不完整类型成员:C.h中未包含Location.h,直接声明struct location loc;,location属于不完整类型,无法作为类的成员变量,导致编译类型检查出错。
  3. P类拷贝初始化问题:Main.cpp中P p = P();是拷贝初始化,而P类包含不可拷贝的std::mutex成员,其拷贝构造函数已被隐式删除,该写法会触发潜在拷贝错误。

修复步骤

  1. 完善C.h的头文件依赖:在C.h顶部添加#include "Location.h",确保location是完整类型:

    #ifndef A_C_H
    #define A_C_H
    
    #include <string>
    #include <thread>
    #include <chrono>
    #include <atomic>
    #include "Location.h" // 添加该行
    
    class P;
    // ... 其余代码不变
    
  2. 显式禁用C类的拷贝操作:在C类的public区域添加拷贝构造和赋值运算符的删除声明,避免意外触发拷贝:

    class C {
        // ... 私有成员不变
    public:
        C() = default;
        ~C() = default;
        C(const C&) = delete; // 添加该行
        C& operator=(const C&) = delete; // 添加该行
    
        // ... 其余成员函数不变
    };
    
  3. 修改Main.cpp的P对象初始化方式:将P p = P();改为直接默认构造,避免拷贝初始化:

    int main() {
        P p; // 替换原有的P p = P();
    
        p.add_child("C1");
        p.add_child("C2");
        p.add_child("C3");
    
        char input;
        std::cin >> input;
    
        p.del();
    }
    

死锁问题解决

死锁原因

P::del()函数中,主线程先获取mut互斥锁,然后调用c->wait()等待子线程结束;而子线程的run()函数中会调用p->get_data(),该函数需要获取mut互斥锁。此时主线程持有锁等待子线程,子线程等待锁释放,形成循环等待,触发死锁。

修复步骤

修改P::del()函数,拆分锁的持有范围:先加锁设置终止标志,释放锁让子线程完成退出逻辑,最后再加锁清理列表:

void P::del() {
    // 第一步:加锁设置终止标志
    {
        std::lock_guard<std::mutex> lg(mut);
        for (auto& c : C_List)
            c->terminate = true;
    } // 此处自动释放锁,子线程可获取锁执行get_data()

    // 第二步:等待所有子线程退出,无需持有锁
    for (auto& c : C_List)
        c->wait();

    // 第三步:重新加锁清理列表
    std::lock_guard<std::mutex> lg(mut);
    C_List.clear();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:33:20