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

Windows C++多线程环境下recv函数崩溃问题求助

TCP多线程服务器recv处崩溃的排查与修复

核心崩溃原因:线程对象未正确管理

你的main函数中,每次循环创建std::thread t后,未调用t.join()或t.detach()。当循环迭代结束时,临时线程对象t被销毁,若此时线程仍在运行,C++标准会触发std::terminate()直接终止程序,这就是无提示崩溃的直接原因。

修复代码:

while (true)
{
    int fd = server.loop();
    if (fd < 0) {
        spdlog::error("Accept failed");
        continue;
    }
    std::thread t(newclient, fd);
    t.detach(); // 让线程后台独立运行,避免对象销毁触发程序终止
}

次要问题:recv_str缓冲区追加逻辑错误

在recv_str()中,当bytes_received小于CHUNK_SIZE时,你仍追加了整个buffer的CHUNK_SIZE字节内容,这会把缓冲区中未被填充的垃圾数据混入结果字符串,可能引发后续逻辑异常或间接内存问题。

修复代码:

} else {
    // 仅追加实际接收到的字节数
    rcv.append(buffer.cbegin(), buffer.cbegin() + bytes_received);
}

其他潜在问题与优化

  • 无效文件描述符校验:
    检查server.loop()(封装accept的逻辑)的返回值,若accept失败返回-1,后续将无效fd传给recv会触发错误。在创建线程前增加校验:

    int fd = server.loop();
    if (fd < 0) {
        spdlog::error("Accept failed, err: {}", WSAGetLastError());
        continue;
    }
    
  • 客户端断开后的死循环处理:
    Handler::loop()中,客户端断开时recv_str返回空字符串,当前用continue会导致无限循环调用recv_str,浪费CPU资源,应直接退出循环:

    while(true){
        buffer.erase();
        buffer = communication.recv_str();
        if (buffer == "") {
            break; // 客户端断开,终止循环
        }
        // 处理接收到的数据
    }
    
  • 错误输出的线程安全优化:
    多线程环境下std::cout存在线程安全风险,改用你已使用的spdlog输出错误,并在出错时直接返回空字符串终止接收:

    if ( bytes_received < 0 ) {
        spdlog::error("recv failed, err: {}", WSAGetLastError());
        return "";
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:15:12