【问题标题】:C++/Qt: crash on QCoreApplicationPrivate::sendPostedEventsC++/Qt:在 QCoreApplicationPrivate::sendPostedEvents 上崩溃
【发布时间】:2013-10-03 13:04:14
【问题描述】:

我在修复以下问题/崩溃时遇到了困难。该程序仅持续运行大约 30 分钟,然后崩溃。基本上程序所做的是(简化):

runCalculations(const InputValues &dataIn, OutputValues &dataOut);
appendNewOutputValues(const OutputValues &dataOut){
   doSomeVerifications(dataOut);
   emit dataChanged(dataOut);
}
//In another class I'm listening to the signal and adding each dataOut to a QMap<QDateTime, QVariant>
onDataChanged(const OutputValues &dataOut){
   addToMap(dateTime, dataOut);
   emit mapChanged();
}

//After that I'm emitting a signal that the buffer was changed: This signal is connected to an QObject which takes new value and does some functionality with it.
onMapChanged(){
   map.getNewData(&newData);
   doSomethingWithNewData(newData);
}

我希望从上面的例子中应该清楚主要思想。

大约每秒发送 2400 个信号。我使用的所有数据大约需要 14MB,所以应该没问题。

首先我认为问题在于我的事件队列已满,所以我在每个 runCalculations() 之后添加了以下代码:

QCoreApplication::instance()->sendPostedEvents();
QCoreApplication::instance()->processEvents();
QCoreApplication::instance()->sendPostedEvents(0, QEvent::DeferredDelete);

我也尝试过只使用 processEvents、sendPostedEvents……但结果相同。 当我只使用 runCalculations 方法(不更新和发送信号)运行我的程序时,一切正常。问题是从调试信息来看我不是很聪明。

我在 Parallels 上运行 XP,我有专用的 3GB 内存和 2 个内核。

回溯:

Thread 1 (Thread 3484.0x3ec):
#0  0x08b05fe0 in abort () from C:\Qt\4.8.4\bin\QtCored4.dll
No symbol table info available.
#1  0x08b6013d in __gnu_cxx::__verbose_terminate_handler () at ../../../../gcc-4.4.0/libstdc++-v3/libsupc++/vterminate.cc:93
    terminating = true
    t = <optimized out>
#2  0x08b0db8d in __cxxabiv1::__terminate (handler=0x8b60018 <__gnu_cxx::__verbose_terminate_handler()>) at ../../../../gcc-4.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:38
No locals.
#3  0x08b73efb in std::terminate () at ../../../../gcc-4.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:48
No locals.
#4  0x08b76956 in __cxxabiv1::__cxa_rethrow () at ../../../../gcc-4.4.0/libstdc++-v3/libsupc++/eh_throw.cc:116
    globals = 0x188f5f4c
    header = 0x762a7b90
#5  0x08aa69c3 in QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=0, data=0x178e6ad0) at kernel/qcoreapplication.cpp:1582
    pe = @0x4e717fe0: {receiver = 0x178e6ce8, event = 0x0, priority = 0}
    e = 0x1adc1018
    r = 0x178e6ce8
    locker = {val = 395209469}
    startOffset = 0
    i = @0x178e6af4: 1
#6  0x08acb347 in qt_internal_proc (hwnd=0x5203ca <FMDataVerificator::createSockets()+3930>, message=1025, wp=0, lp=0) at kernel/qeventdispatcher_win.cpp:496
    localSerialNumber = 540804d
    msg = {hwnd = 0x5203ca <FMDataVerificator::createSockets()+3930>, message = 1025, wParam = 0, lParam = 0, time = 2285040, pt = {x = 2285016, y = 145536386}}
    app = 0x22fe70
    q = 0x178e6ce8
    result = 0
    d = 0x178e6d08
#7  0x7e418734 in USER32!GetDC () from C:\WINDOWS\system32\user32.dll
No symbol table info available.

【问题讨论】:

  • 一般来说,你在某个地方有一个内存错误,它对其余代码造成了严重破坏。你需要不断地最小化你的代码,直到你找出你的错误所在。我投票结束这个问题,因为如果没有仍然重现问题的最小测试用例,就不可能回答。此外,事件队列不可能溢出,因为它没有大小限制。如果您发送事件的速度超过了它们的处理速度,您可能会耗尽内存,但这是另一个问题。

标签: c++ qt qtcore


【解决方案1】:

据我所知,我认为您不能超过事件队列的容量。在指向QtCore 中的某些内容之前,我会先看看其他地方。

http://qt-project.org/doc/qt-4.8/eventsandfilters.html

这很可能是同步问题或内存泄漏问题,甚至可能是内存访问问题。

内存泄漏?

要排除内存泄漏问题,请查看任务管理器,并查看堆上程序的大小。 (内存栏)。如果它在整个 30 分钟内继续增长,则可能是内存泄漏。

内存访问?

要查看是否是内存访问问题,您可能正在“清理”一个对象,然后再次引用它,或者引用尚未实例化的指针。

要解决此问题,对于在堆上创建的任何对象,请在构造函数中将其清零,甚至创建一个 void init_mem() 函数将所有堆项目设置为零。

然后,当您删除任何内容时,请确保之后也将其设置为零。

然后在访问任何指针之前,检查以确保它们不为空,如果是则返回或打印错误。

同步问题?

最后,如果您遇到同步问题,则必须处理由多个线程访问的任何数据。两个或多个线程之间共享的任何数据都需要被视为问题区域。所以用 QMutexLocker 之类的东西适当地包装它或类似的东西。对另一个线程的调用也应该使用通过队列连接连接的信号和插槽来完成,而不是自动连接或直接连接。

听起来如果你不使用线程,你可能应该使用线程,因为你有生产者/消费者模型。

调试技巧

此外,对于长时间运行的进程,正确使用日志记录和调试语句有助于缩小导致问题的范围。

Adding Qt Sources to QtCreator 2.4.1

http://qt-project.org/doc/qt-4.8/debug.html

希望对您有所帮助。

【讨论】:

  • 非常感谢您的出色回答。关于内存泄漏的一个问题:我将计算数据存储在内存(QMap)中,因此内存使用量会增加。但这并不意味着我有内存泄漏,....对吗?顺便提一句。到目前为止,我的应用程序的使用量约为 150MB,而且还在缓慢增加。
  • 所以堆非常适合放置未知大小的数组和增长的对象,但过一段时间,你可能会用完空间。您可以偶尔清理一些中间值,或者将其中一些发送到文件中吗?谷歌搜索内存泄漏并阅读它也可能会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多