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

QT多线程餐厅模拟程序启动线程时崩溃求助

餐厅模拟QT应用线程启动崩溃问题解决

核心崩溃原因:悬空指针访问

在startRestaurant函数中,你创建的Cook、Waiter、Client、Table都是栈上的局部对象,循环结束后这些对象会被立即销毁,但你把它们的地址存入了QList。后续调用cookList.value(1)->startCook()时,访问的是已经被释放的内存,直接触发程序崩溃。

解决方案:改用堆内存创建对象

将栈对象改为new创建的堆对象,手动控制对象生命周期:

// 厨师创建逻辑修改
for(int i=0; i<totalChefs; i++){
    QString output = QStringLiteral("Cook %1").arg(i);
    Cook* cook = new Cook(i, output);
    cookList.append(cook);
}

// 服务员、顾客、餐桌同理修改
for(int i=0; i<totalWaiters; i++){
    QString output = QStringLiteral("Waiter %1").arg(i);
    Waiter* waiter = new Waiter(i, output);
    waiterList.append(waiter);
}

for(int i=0; i<totalClients; i++){
    QString output = QStringLiteral("Client %1").arg(i);
    Client* client = new Client(i, output);
    clientList.append(client);
}

for(int i=0; i<totalTables; i++){
    QString output = QStringLiteral("Table %1").arg(i);
    Table* table = new Table(i, output, false);
    tables.append(table);
}

QThread使用错误:直接调用run()而非start()

你自定义的startCook()、startWaiter()、startClient()直接调用了run()函数,这只是在当前线程同步执行代码,并没有真正启动新线程。QThread的正确用法是调用start()方法,它会自动在新线程上下文执行run()逻辑。

解决方案:移除自定义启动函数,调用标准start()

  1. 删除Cook类的startCook()、Client类的startClient()、Waiter类的startWaiter()。
  2. 修改启动代码:
// 替换原启动逻辑
cookList.value(1)->start();
waiterList.value(1)->start();
clientList.value(1)->start();

其他潜在问题修复

1. Table类的setClient传值问题

Table::setClient(Client newClient)是传值调用,会创建Client对象副本,无法关联原对象。改为传指针:

// table.h修改
void setClient(Client* newClient);

// table.cpp修改
void Table::setClient(Client* newClient){
    if(newClient){
        this->clientId = newClient->getId();
        this->seat = true;
    }
}

2. QSemaphore未初始化问题

Cook、Client、Waiter类中定义的QSemaphore semaphore默认初始值为0,后续业务逻辑中如果需要控制并发,需根据场景初始化信号量(比如Cook类控制烹饪并发数时,构造时传入允许的数量)。

3. 内存泄漏问题

用new创建的对象需在合适时机释放,在Restaurant类中添加析构函数:

// restaurant.h添加析构函数声明
~Restaurant();

// restaurant.cpp实现析构函数
Restaurant::~Restaurant(){
    for(Cook* cook : cookList) delete cook;
    for(Waiter* waiter : waiterList) delete waiter;
    for(Client* client : clientList) delete client;
    for(Table* table : tables) delete table;
}

完成以上修改后,线程启动时不会再因悬空指针崩溃,且能正确创建并运行新线程。

内容的提问来源于stack exchange,提问作者Yitzhack Ramirez Quiros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 15:15:36