2

我在解决以下问题/崩溃时遇到了困难。该程序仅持续运行大约 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 个内核。

qt_internal_proc QCoreApplication

回溯:

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.
4

1 回答 1

3

据我所知,我认为您不能超过事件队列的容量。在指向QtCore.

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

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

内存泄漏?

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

内存访问?

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

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

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

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

同步问题?

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

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

调试技术

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

将 Qt 源添加到 QtCreator 2.4.1

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

希望有帮助。

于 2013-10-03T17:39:33.230 回答