在实现多线程C/S通信时,有一个bug卡了我好久——当有一个C端关闭时,S端会崩溃。
经过一条条函数语句的筛查,终于找到问题出在哪里:
我通过类QList和迭代器来存储、访问C端链接的socket,而我在deleteSocket中delete迭代器后还想要访问到它,导致了内存的异常访问,使程序崩溃了。所以把delete *iter改成(*iter)->deleteLater(); 既可以实现原来释放内存的作用,又不会使程序崩溃
void MyTcpServer::deleteSocket(MyTcpSocket *mysocket)
{QList<MyTcpSocket*>::Iterator iter=m_tcpSocketList.begin();
// qDebug()<<"deleteSocket触发";
for(;iter!=m_tcpSocketList.end();iter++)
{
// qDebug()<<"deleteSocket进入循环";
if(*iter==mysocket)
//删除list容器中的节点以及socket
{
//原先写的 delete *iter,导致程序一直崩溃
(*iter)->deleteLater();//延迟释放空间,否则会导致崩溃
*iter=NULL;
qDebug()<<"成功deleteSocket";
m_tcpSocketList.erase(iter);
qDebug()<<"成功erase";
break;
}
}for(int i=0;i<m_tcpSocketList.size();i++)
{
// qDebug()<<m_tcpSocketList.at(i)->getName();
}
}
附上在寻找BUG中GPT给出的C端关闭可能导致S端崩溃的原因 (尽管没什么鸟用)
在QT中,如果客户端(C端)关闭后服务器端(S端)崩溃,可能是由于以下几个原因:
1. **未处理的异常**:程序中可能存在未被正确捕获和处理的异常。在程序的主循环或关键部分添加异常处理代码,确保所有异常都被正确处理,可以避免程序在关闭时崩溃。
2. **资源释放不当**:确保在程序中使用的资源(如文件、内存等)在不再使用时得到正确的释放。使用RAII(Resource Acquisition Is Initialization)技术可以帮助自动管理资源的释放,确保程序的正常关闭。
3. **线程退出逻辑问题**:在关闭程序时,需要确保所有线程都已经正确退出并释放了资源。可以使用线程同步机制(如互斥锁、条件变量等)来协调线程的退出。
4. **Qt版本bug**:有时候,Qt版本可能存在一些已知的bug,导致程序在关闭时崩溃。尝试更新到最新的Qt版本,看是否能解决问题。
5. **socket操作问题**:如果在客户端关闭连接时,服务器端的QTcpServer对象被析构,而此时socket还没有正确关闭,可能会导致崩溃。确保在断开socket之前,socket已经被正确关闭。
6. **内存泄漏**:如果程序中存在内存泄漏,可能会导致系统资源耗尽,从而引起崩溃。检查程序是否存在内存泄漏,并修复相关问题。
7. **TCP连接关闭方式**:了解不同的TCP连接关闭方式,并选择适当的关闭方法。例如,调用close()方法来关闭socket,而不是依赖于进程的正常结束来关闭连接。
8. **网络编程错误**:检查网络编程的逻辑,确保没有错误的读写操作或者错误的信号槽连接。例如,确保在使用write()方法后,调用flush()方法来确保数据被发送出去。综上所述,为了解决QT中C端关闭后S端崩溃的问题,您可能需要从异常处理、资源管理、多线程退出、Qt版本更新、socket操作、内存管理以及网络编程逻辑等多个方面进行排查和调试。