QT程序数据库操作,大量消耗句柄的问题

程序心声 2019-08-13 08:55:36
大家好,我想请求大家帮忙一个问题。我用QT平台,开发了一个有关数据库的程序。用的方式就是网上看到的基本的数据库操作。我先写了一个实验程序,是没有问题的,保存了一百万条数据,都是正常运行的。然后把我测试过的代码,放入我的新程序中,就出现了一个问题。
我在Widget类中,加了一个回调函数。如果收到硬件发给我的中断,先触发回调函数,回调函数是静态非成员函数。回调函数被触发之后,会发送事件给Widget类中的一个成员函数。Widget类中的这个成员函数,具体作用就是把得到的数据进行保存。保存数据的代码就是我前面实验过的数据库的代码。整个程序是可以正常运行的,但是会出现一个巨大的问题,就是程序一直在申请很多句柄。随着保存的数据量越大,句柄量越来越多,到最后,整个系统的句柄都被用完了,系统没办法进行任何操作。我在任务管理器中看了,内存没有消耗,CPU也没有,就是句柄在疯狂的增加。程序跑在Win7的系统上,操作系统直接提示,系统资源耗尽,什么都点不了,最后只能重启电脑。
数据库操作部分的大概逻辑如下


QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
database.setDatabaseName("VMIC_DataBase.db");
database.transaction();
for (int i = 0; i < NUM; i++)
{
QString qsStr;
qsStr.sprintf("insert into member values(%d, '%s')", nDatabaseID, cRecBufAssem[i]);
bool success = query.exec(qsStr);
}
if(!QSqlDatabase::database().commit())
{
qDebug() << QSqlDatabase::database().lastError(); //提交
if(!QSqlDatabase::database().rollback())
{
qDebug() << QSqlDatabase::database().lastError(); //回滚
}
}

经过我的排查,其中消耗句柄的应该就在这里:
QString qsStr;
qsStr.sprintf("insert into member values(%d, '%s')", nDatabaseID, cRecBufAssem[i]);
bool success = query.exec(qsStr);
我想问一下大家,为什么会出现这种情况,我之前的实验程序,也有这个语句,怎么就没有消耗句柄呢。这个问题要怎么解决,如何不申请或者说能够释放掉句柄呢。
谢谢大家,在线等。
...全文
2345 26 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
lq77630 2019-08-18
  • 打赏
  • 举报
回复
会不会是其他问?
  • 打赏
  • 举报
回复
搞不懂哎。。。
赵4老师 2019-08-15
  • 打赏
  • 举报
回复
"Qt是开源的“ 下载Qt源代码,看query.exec方法对应的若干行源代码,分析是哪句申请了操作系统的句柄资源,对应该句柄资源又是在query对应类或其它相关类中释放的。 由此你就可以在你的代码适当位置调用释放该句柄的方法。 反正我估计总不至于因此你发现人家大名鼎鼎的Qt源代码有句柄泄露的bug
程序心声 2019-08-15
  • 打赏
  • 举报
回复
引用 19 楼 赵4老师 的回复:
query.exec对Qt源代码来说,不是一句,是很多很多句。

我不明白,这怎么是很多句,那要如何排查,要如何分写成一句一句的,我还真不明白。请你讲解一下,愿闻其详。
godorochi 2019-08-15
  • 打赏
  • 举报
回复
顶顶顶顶顶顶顶顶顶!!!!
赵4老师 2019-08-15
  • 打赏
  • 举报
回复
query.exec对Qt源代码来说,不是一句,是很多很多句。
老葱1# 2019-08-15
  • 打赏
  • 举报
回复
建议 不使用 addDatabase 试试, 即回调函数中, 临时分配db, 退出回调保证释放干净, 没必要做 db 链接管理, 不就是一个参数传递吗, 多线程环境下 , 缺省db 会有啥效果真搞不明白。 除非 QSqlDatabase::addDatabase() 和下面的 commit 代码是 同一个函数? 看你 commit 时用的是取缺省db, 应该 不是同一个函数 , 那么函数包含 ? 若不是包含的话, 就很难说了。 QT 对象的自动化管理,做的不干净,很讨厌的, 我的图形还有内存泄漏呢(监控, 2秒刷数据, 一天会增加50M),分析来分析去,只能认为底层问题, 比 以前自己GDI 的差多了,QT的图形框架差,性能差,还泄漏, 一般包装过度的东西都不好用。 第3方 连接池服务,正在文档中, https://mp.csdn.net/postedit/99645027
老葱1# 2019-08-15
  • 打赏
  • 举报
回复
QT 包装过头了,不适合C++新手, 更加不建议使用QT 的网络/数据库类, 线程类都没啥意义。 用它的界面就够了。
edswang 2019-08-15
  • 打赏
  • 举报
回复
引用 1 楼 赵4老师 的回复:
将query换成connect
good
走好每一步 2019-08-15
  • 打赏
  • 举报
回复
或者你觉得赵老师姿态有点高了,有点装逼了,我真不觉得。 我有好几个问题都是看QT源码解决了,你觉得如果是装逼的,那你按照你认为地去做就好了。
走好每一步 2019-08-15
  • 打赏
  • 举报
回复
楼主,别人只是告诉你一个方向,你指望别人帮你解决问题。。。 你请赵老师吃饭了? 我觉得赵老师有时候确实喜欢讲一些玄乎的东西,但是看QT源码确实可以解决你的问题啊,我经常遇到问题都看QT源码的啊 exec里面是做了很多步的。。。 还有我说你可以在贴中让你把软件的源码贴出来,你贴了吗。。。 你自己并没有去认真去吸取回帖者的意见,责怪别人不帮你解决问题就有点那个啥了吧
赵4老师 2019-08-15
  • 打赏
  • 举报
回复
八竿子打不打得着自有明白人定论。
程序心声 2019-08-15
  • 打赏
  • 举报
回复
引用 22 楼 赵4老师 的回复:

赵4你好,你的回答让我有些意外。我在这里问问题,不代表我要找大名鼎鼎的QT的任何漏洞,我问问题,只是因为我不知道这个问题怎么解决,我没遇到过,不会处理,怎么叫我是找漏洞。照你这么说,凡是在CSDN上提问的人,都是跑来看人家开发工具不顺眼,都是来找漏洞的?那人都不允许不懂问题是吗?
我问的意思,不是说这句话有漏洞,是看应该怎么用,我的用法有没有问题,或者说,用完了还有什么其他的步骤,我没有做的,又或者不应该怎么用,等等,等等。怎么叫我是找人家的问题?你的说法还真是荒唐啊,我第一次见这样的。
赵4,我见你很久了,很多年前就在CSDN,你是老资历了,我本来应该尊敬你。可你以前在论坛里回复,就是不看别人的问题,八杆子打不着的就先贴一段话,很多人都觉得你这样做很无聊。这回呢,又是答非所问。我一追问,就变成我要找漏洞,这么荒唐的说法,我还是第一次听到!如果你是这样的态度,你可以不用回答啊,为什么要埋汰人呢?!
慕思暗 2019-08-15
  • 打赏
  • 举报
回复
下载Qt源代码,看query.exec方法对应的若干行源代码
weixin_41542472 2019-08-15
  • 打赏
  • 举报
回复
下载Qt源代码,看query.exec方法对应的若干行源代码,分析是哪句申请了操作系统的句柄资源,对应该句柄资源又是在query对应类或其它相关类中释放的。
由此你就可以在你的代码适当位置调用释放该句柄的方法。

反正我估计总不至于因此你发现人家大名鼎鼎的Qt源代码有句柄泄露的bug
弓人水 2019-08-14
  • 打赏
  • 举报
回复
试试这个方法呢:QSqlDatabase::exec(const QString &query = QString()) const
程序心声 2019-08-14
  • 打赏
  • 举报
回复
引用 6 楼 倚栏|听风 的回复:
是不是和多线程有关?

但我这应该不属于多线程啊,只是在 Widget类中,调用DLL的时候,注册了一个回调函数。而这个回掉所调用的,是静态非成员函数。虽然不属于 Widget类的成员,但是也不是另外开的线程啊。而且,如果我不做数据库操作,只让回调和发送事件,句柄是没有变化的。只要把数据库操作加上,才会有句柄增加。
倚栏|听风 2019-08-14
  • 打赏
  • 举报
回复
是不是和多线程有关?
程序心声 2019-08-14
  • 打赏
  • 举报
回复
引用 3 楼 弓人水 的回复:
1、NUM的值大概是多少?
2、判断是不是支持事务呢?database.driver()->hasFeature(QSqlDriver::Transactions)
代码最好能贴全一些。

代码太多了,我都贴上去,很杂乱,别人也很难看明白。主要的代码我贴上去了,思路就是我说的思路。NUM的值是10,每得到十个值,做一次事务。因为中断是有间隙的,这样是为了提高效率。
其实和事务没关系,我即使把事务注释掉,不用事务,只要还有数据库操作,句柄还是一直往上涨,我用排除法,最后判断,就是在 query.exec 这句,其他部分注释掉,都对问题没有影响。只要不执行 query.exec 这句,句柄就停了。奇怪的是,为什么会出现这种问题,为什么在验证程序不出现。如果不用 query.exec ,还有什么别的方法可以执行插入或保存数据。
程序心声 2019-08-14
  • 打赏
  • 举报
回复
引用 3 楼 弓人水 的回复:
1、NUM的值大概是多少?
2、判断是不是支持事务呢?database.driver()->hasFeature(QSqlDriver::Transactions)
代码最好能贴全一些。

代码太多了,我都贴上去,很杂乱,别人也很难看明白。主要的代码我贴上去了,思路就是我说的思路。NUM的值是10,每得到十个值,做一次事务。因为中断只有间隙的,这样是为了提高效率。
其实和实物没关系,我即使把事务注释掉,句柄还是一直往上涨,我用排除法,最后判断,就是在 query.exec 这句,其他部分注释掉,都对问题没有影响。只要不执行 query.exec 这句,句柄就停了。奇怪的是,为什么会出现这种问题,为什么在验证程序不出现。如果不用
query.exec ,还有什么别的方法可以执行插入或保存数据。
加载更多回复(12)

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧