关于QSocket的释放的一个需要注意的情况

最近在用QtNetwork编写服务器程序进行TCP/IP通信,大体过程如下:

1. 创建一个QTcpServer实例,监听目标IP和端口;

2. 一旦监听到有连接,获取和客户端之间的socket;

3. 使用socket进行通信;

4. 通信结束后,可以手动释放socket,也可以不管它,在释放QTcpServer的时候会把其下的所有socket全部自动释放。

在编写时,我做了如下事:

TcpNetwork::TcpNetwork()
{
    ...
    connect(mySocket, SIGNAL(disconnect(QTcpSocket*)), this, SLOT(ServerConnectionLost(QTcpSocket*)));
    ...
}
TcpNetwork::~TcpNetwork()
{
    if (tcpServer != NULL)
    {
        delete tcpServer;
    }
}
<pre name="code" class="cpp">void TcpNetwork::ServerConnectionLost(QTcpSocket *socket)
{
    if (socket == mySocket)
    {
        ...
        // debug
        delete mySocket;
        mySocket = NULL;
        ...
    }
}

这样在关闭程序窗口时会导致崩溃,看了一下QTcpServer的析构函数源码后发现,在析构时Qt会首先检查QtcpServer下的socket指针所指向内存是否已被释放,然后执行每个socket的关闭操作,随后释放刚才被检查过的未被释放的socket内存,最后释放QTcpServer。

如果将QTcpSocket::disconnect()信号与一个其中带有释放socket操作的槽连接起来,那么如果socket还没有关闭就直接析构QTcpServer,在执行断开socket这一步时(如果之前已经断开了就不会再执行这一步了)会触发带有删除socket操作的槽,然而析构函数对此一无所知,紧接着便是析构函数来释放socket,也就造成了socket的内存的重复释放,导致崩溃。

解决方法:在关闭窗口之前先关闭socket,这样在析构函数中就不会再执行关闭socket的操作。或者不在连接断开时添加含有释放socket操作的槽。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 20:49:07

关于QSocket的释放的一个需要注意的情况的相关文章

关于QSocket的释放的一个需要注意的情况(必须先断开连接)

最近在用QtNetwork编写服务器程序进行TCP/IP通信,大体过程如下: 1. 创建一个QTcpServer实例,监听目标IP和端口: 2. 一旦监听到有连接,获取和客户端之间的socket: 3. 使用socket进行通信: 4. 通信结束后,可以手动释放socket,也可以不管它,在释放QTcpServer的时候会把其下的所有socket全部自动释放. 在编写时,我做了如下事: [cpp] view plain copy TcpNetwork::TcpNetwork() { ... co

[ASP.NET]EF选一个空表的情况

public List<DAL.StuFillAnswers> FillsToCheck(int sid,int eid) { using (DAL.ExamSysEntities db = new DAL.ExamSysEntities()) { return db.StuFillAnswers.Where(x => x.StuID == sid && x.ExamID == eid).ToList(); } } 返回的是count为0的list [ASP.NET]EF

一个根据内存使用情况重启tomcat的小脚本

有一台服务器上部署了tomcat,随着时间的推移,内存消耗越来越大,所以写了一个小脚本配合crontab定时检测内存,不足的情况下重启tomcat. #!/bin/bash #tomcat restart:out of memory LOG=./restart_tomcat.log TOMCAT=/tomcat/bin/ TOMCATDIR=/tomcat echo"----------------------------" >> $LOG mem_total=$(free

【原创】一个普适于各种情况易于操作的高可用服务器部署方案

一个大型的互联网系统,采用负载均衡原理实现高可用是最基本的要求,几年前,要想做到这点,得是大公司,找牛逼的技术员才行,现在,阿里云出来之后,门槛极大降低,让运营方可以全心去做运营,不用再为技术方面考虑太多,下图是一个比较典型的利用阿里云提供的各项服务,搭建的一个可水平扩展的部署方案. 这个方案有以下特点: 1.技术难度不高 一般来说,只需要对session和文件保存这两块的代码稍作修改,实现集中存取即可 2.成本费用低 充分利用阿里云的可灵活升级策略,根据系统负载,逐步升级配置 3.达成高可用

三种方式实例化一个类的性能情况

源内容:http://www.cnblogs.com/shouce/p/5558095.html#undefined 下面的内容是根据“源内容”进行了整改.补充. 三种方式实例化一类,包括无参数构造形式与有参数构造形式性能测试. 使用new关键字创建类实例(常用方式). 使用Activator激活器类创建类实例(Activator用以在本地或从远程创建对象类型,或获取对现有远程对象的引用). 使用Assembly程序集创建类实例(Assembly表示一个程序集,它是一个可重用.无版本冲突并且可自

C++的auto在用多维数组进行初始化时一个易混淆的情况

先看下面这段程序: int arr[1][10] = {0,1,2,3,4,5,6,7,8,9}; for (auto *p = arr;p != end(arr); p++){ cout << "p is " << typeid(p).name() <<endl; cout << "*p is " << typeid(*p).name() <<endl; } for (auto *q : ar

mysql中把一个表的数据批量导入另一个表中(不同情况)

mysql中把一个表的数据批量导入另一个表中 不管是在网站开发还是在应用程序开发中,我们经常会碰到需要将MySQL某个表的数据批量导入到另一个表的情况,甚至有时还需要指定导入字段. 本文就将以MySQL数据库为例,介绍如何通过SQL命令行将某个表的所有数据或指定字段的数据,导入到目标表 中. 类别一. 如果两张张表(导出表和目标表)的字段一致,并且希望插入全部数据,可以用这种方法:(此方法只适合导出两表在同一database) INSERT INTO 目标表 SELECT * FROM 来源表;

查询员工最后一个月的工资情况

select * from employee empid  name 001 张三 002 李四 003 王五 select * from salary empid  month salary 001   1    100 001   2    200 001   3    300 002   1    200 002   2    400 003   3    500 select t3.name , t1.empid,t1.month,t2.salary from ( select empi

在远程连接一个 Wndows 10的情况下,重启远程机器

如果你从菜单找的话,是找不到这个菜单的!!! 你应该直接按 alt + F4 , 就会出现这个选项了. 参考: https://tommynation.com/shut-windows-10-remote-desktop-rdp/ 原文地址:https://www.cnblogs.com/johnsonshu/p/8432467.html