PDA

View Full Version : Devision By Zero Error while emitting signal



thomers
10th October 2011, 13:56
Hi,

I have sort of a big problem: my qt app is more or less randomly throwing a "integer division by zero"-error while processing an emitted signal (the function created in the moc'd cpp file).

This is the situation:
- Qt App with a QGraphicsView containing one PixmapItem that repeatedly gets updated and one QDeclarativeComponent for the UI that overlays the PixmapItem.
- I have one QThread that collects data from a picture grabbing device and once finished grabbing enough data it emits a "onNewImage()" signal without any parameters.
- the according slot "newImage()" in my MainWindow then creates a QImage/QPixmap from the data (BYTE *) and gives this image to the PixmapItem

In general, this work very much to my satisfaction.

But now an then, an more or less reproducible (3 out of 10), my app gets an "integer devision by zer"-error an crashes:
http://img12.imageshack.us/img12/7442/errormessages.th.png (http://img12.imageshack.us/i/errormessages.png/)
This error is thrown INSIDE the handling of the emitted signal in the according moc'd cpp file:
http://img69.imageshack.us/img69/2223/errorsignal.th.png (http://img69.imageshack.us/i/errorsignal.png/)
This is what the debugger-log says:
http://img546.imageshack.us/img546/4867/errordebuglog.th.png (http://img546.imageshack.us/i/errordebuglog.png/)

FYI: I do not even have one division in the whole code ...

And here some snippets:
- emitting function in Thread:
void GrabberController::run() {

if(!_inited)
return;
_fpsTimer.start();

_running = true;

while(_running) {
if(_grabber->Download(_data)) {
_fps++;
emit onNewImage();
}
else
qDebug(_grabber->GetLastError().c_str());

}

_running = false;
}

with:

signals:
void onNewImage();


- the receiving end:
void MainWindow::newImage() {

QSize size = _grabber->imageSize();
_currentImage = QImage(_grabber->data(), size.width(), size.height(), _grabber->imageFormat());
if(_currentImage.isNull())
return;

//_imgItem.setImage(_currentImage);
_pixItem.setPixmap(QPixmap::fromImage(_currentImag e));
_graphicsView->update();
}

with:
connect(_grabber, SIGNAL(onNewImage()), SLOT(newImage()), Qt::QueuedConnection);

- and finaly the error throwing moc'd cpp:
/************************************************** **************************
** Meta object code from reading C++ file 'grabbercontroller.h'
**
** Created: Mon 10. Oct 13:28:02 2011
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.4)
**
** WARNING! All changes made in this file will be lost!
************************************************** ***************************/

#include "../grabbercontroller.h"
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'grabbercontroller.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 62
#error "This file was generated using the moc from 4.7.4. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
static const uint qt_meta_data_GrabberController[] = {

// content:
5, // revision
0, // classname
0, 0, // classinfo
3, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
2, // signalCount

// signals: signature, parameters, type, tag, flags
19, 18, 18, 18, 0x05,
36, 32, 18, 18, 0x05,

// slots: signature, parameters, type, tag, flags
47, 18, 18, 18, 0x0a,

0 // eod
};

static const char qt_meta_stringdata_GrabberController[] = {
"GrabberController\0\0onNewImage()\0fps\0"
"onFps(int)\0updateFps()\0"
};

const QMetaObject GrabberController::staticMetaObject = {
{ &QThread::staticMetaObject, qt_meta_stringdata_GrabberController,
qt_meta_data_GrabberController, 0 }
};

#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &GrabberController::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION

const QMetaObject *GrabberController::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}

void *GrabberController::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_GrabberController))
return static_cast<void*>(const_cast< GrabberController*>(this));
return QThread::qt_metacast(_clname);
}

int GrabberController::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QThread::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onNewImage(); break;
case 1: onFps((*reinterpret_cast< int(*)>(_a[1]))); break;
case 2: updateFps(); break;
default: ;
}
_id -= 3;
}
return _id;
}

// SIGNAL 0
void GrabberController::onNewImage()
{
QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

// SIGNAL 1
void GrabberController::onFps(int _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
}
QT_END_MOC_NAMESPACE


Can anyone help me here?

Cheers

Thomas

d_stranz
10th October 2011, 16:59
From what I can see of your code, you are running a multi-threaded process with absolutely no locking or other synchronization on the memory you are using to store the grabbed data. You seem to be using the same _grabber instance in both threads.

My guess is that the divide by zero error is just a symptom of the fact that your two threads are managing to completely corrupt your image data, because one of them continues to write to the _grabber->data() while the other is reading from it. Try wrapping the reading / writing calls in a mutex or other locking mechanism and see if that fixes the synchronization problem, or copy the data you have grabbed and pass that to the main GUI process instead of directly reading from your grab buffer.

thomers
11th October 2011, 08:57
Ok, sry, my bad. I forgot to explain, that in the first code piece _grabber is an instance of the actual Grabber-Class and _grabber in the second code is an instance of the threaded class GrabberController.

So, there is just the GUI and this GrabberController-Thread. I checked for any synch problems but as far as I see ther are none.

The GrabberController-Thread emits the signal onNewImage and does not continue and alter _data until the according slot newImage of the MainWindows has finished building and displaying the image. So there should be no problems at this point.

Or am I mistaken?

EDIT: tried copying the data before building the image but did not change a bit

thomers
12th October 2011, 14:21
Well, since I cannot edit my previous post, I will have to reply to update the situation:

I removed the connect-line in my MainWindow (connect(_grabber, SIGNAL(onNewImage()), SLOT(newImage()), Qt::QueuedConnection);), so that emitting the signal in the worker thread should end in void, but I still get an Division By Zero error, this time at the app.exec() line in my main() function. This puzzles me, since absolutely nothing is done with anything.
But when I remove the emit onNewImage() line in the worker thread, I get no errors at all (but the data grabbing mechanism still works, proven by the FPS ...)

So, still no idea whats going bananas here. Hoping for help.

Cheers

Thomas

ChrisW67
13th October 2011, 09:39
Clean the project, re-run qmake, and rebuild the project. Does the problem persist?

thomers
17th October 2011, 19:42
@ChrisW67: was actually the first thing I did and did it many many times again but no changes there.
Also tried compiling on differen machines with different version of Qt but always this crappy error I can not find a reason for.

It begins to look like I have to switch back to C# (where it works perfectly with exactly the same libraries etc.), but I would not like it ...

d_stranz
18th October 2011, 00:06
If you are convinced that your inter-thread communication is not corrupting the data, then I would check to be absolutely sure that the QImage you are creating is properly initialized, and has the proper parameters set. I am guessing that it might be possible to get a divide-by-zero fault if, for example, somewhere along the line some code internal to Qt was trying to calculate an aspect ratio for scaling the image, and the denominator turned out to be zero (or uninitialized garbage).

I think you need to take a step back and try to isolate the source of the problem. For example, replace the part of your grabber thread that uses the external library with some emulation code that simply fills your grab buffer with some hard-coded stuff, and see if you still get the problem. Or set up a timer that emulates what is happening in your thread, and call the image creation slot every time it fires.

If you're getting the same problem on every platform and with different versions of Qt, the finger is probably pointing at your code, not something wrong in Qt or your library.