Memory corruption related to signal emission?
I suspect I'm dealing with memory corruption somewhere in my program. I'm getting a SIGSEGV on a call to a function from a trusted third-party library. With some trial and error I've discovered that this segfault happens when the lines
Code:
emit newStreamFound(_streams[streamOneSSRC]);
emit newStreamFound(_streams[streamTwoSSRC]);
are not commented. This happens even when no slots are connected to this signal. As far as I know there are no thread safety issues. I ran a Valgrind memory analysis with these lines disabled and this is what came up:
http://i.imgur.com/c02qm.png
I can't make heads or tails of this output. The test condition in the do while loop depends on one variable that is, in fact, initialized at the top of the function. Does any of this point to issues that should be investigated? If not, what are the next steps I can take?
Re: Memory corruption related to signal emission?
right, so have you debugged the values of streamOneSSRC, and the array value at that index?
Re: Memory corruption related to signal emission?
I should probably mention that _streams is a QMap. streamOneSSRC and streamTwoSSRC are uint32_t with values similar to 738621152 and 3435571404. I've asserted that
Code:
assert(_streams.find(streamOneSSRC) != _streams.end());
assert(_streams.find(streamTwoSSRC) != _streams.end());
right before the signal emission happens.
Re: Memory corruption related to signal emission?
Why do you think this is related to signal emission, and not to accessing the QMap ?
Does it crash if you just print the values ?
Code:
// emit newStreamFound(_streams[streamOneSSRC]);
// emit newStreamFound(_streams[streamTwoSSRC]);
qDebug() << _streams[streamOneSSRC];
qDebug() << _streams[streamTwoSSRC];
Re: Memory corruption related to signal emission?
Nope, that seems to work just fine.
Code:
VideoStream(0x7fffe4110e20)
VideoStream(0x7fffe4110e90)
But then again if I'm dealing with a memory corruption bug this behavior could be undefined.
Re: Memory corruption related to signal emission?
how are you pasing the data through the signaal/slot? const ref?
Re: Memory corruption related to signal emission?
By pointer.
Code:
void newStreamFound(VideoStream*);
_streams is a QMap<uint32_t, VideoStream*>.
Re: Memory corruption related to signal emission?
you've got a problem somewhere else then. emitting a signal with a pointer as an argument, and with no slots connected, does not cause a seg fault.
Re: Memory corruption related to signal emission?
Right... so it's likely to be memory corruption like I thought then? Can you conclude anything from the Valgrind memory analysis about where the error might be?
Re: Memory corruption related to signal emission?
seg fault is always doing something dodgy to memory isnt it?
valgrind doesnt play too nicely with qt from what little I have read about it so not sure you can conclude much from it.
Re: Memory corruption related to signal emission?
Build debug version, launch with debugger and examine (post here) backtrace after crash.
Re: Memory corruption related to signal emission?
I got this from gdb.
Quote:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff711000c in ?? () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
(gdb) backtrace
#0 0x00007ffff711000c in ?? () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#1 0x00007ffff711101a in QPainter::QPainter(QPaintDevice*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#2 0x00007ffff73fdb3d in QFrame::paintEvent(QPaintEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#3 0x00007ffff701325b in QWidget::event(QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#4 0x00007ffff73fd7cb in QFrame::event(QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#5 0x00007ffff6fb2faf in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#6 0x00007ffff6fb9c8b in QApplication::notify(QObject*, QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#7 0x00007ffff6a62dc4 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#8 0x00007ffff700d202 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#9 0x00007ffff700dd32 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevic e*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#10 0x00007ffff700cf7f in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#11 0x00007ffff71ebf6a in ?? () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#12 0x00007ffff7004086 in QWidgetPrivate::syncBackingStore() () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#13 0x00007ffff7013911 in QWidget::event(QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#14 0x00007ffff741a4e1 in QMainWindow::event(QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#15 0x00007ffff6fb2faf in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#16 0x00007ffff6fb9c8b in QApplication::notify(QObject*, QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#17 0x00007ffff6a62dc4 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#18 0x00007ffff6a63ef1 in QCoreApplicationPrivate::sendPostedEvents(QObject* , int, QThreadData*) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#19 0x00007ffff6a90703 in ?? () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#20 0x00007ffff553da5d in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#21 0x00007ffff553e258 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#22 0x00007ffff553e429 in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#23 0x00007ffff6a90a1c in QEventDispatcherGlib::processEvents(QFlags<QEventL oop::ProcessEventsFlag>) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#24 0x00007ffff7065c0f in ?? () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtGui.so.4
#25 0x00007ffff6a62115 in QEventLoop::processEvents(QFlags<QEventLoop::Proce ssEventsFlag>) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#26 0x00007ffff6a62366 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsF lag>) () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#27 0x00007ffff6a641a4 in QCoreApplication::exec() () from /opt/QtSDK/Desktop/Qt/474/gcc/lib/libQtCore.so.4
#28 0x000000000040781f in launchGUI (ip=0x7fffffffe3c6 "127.0.0.1", port=12000) at ../VideoStreamer/main.cpp:36
#29 0x0000000000407795 in main (argc=3, argv=0x7fffffffe068) at ../VideoStreamer/main.cpp:27
Re: Memory corruption related to signal emission?
Can you post the code for launchGUI (or maybe whole main.cpp) ?
Re: Memory corruption related to signal emission?
Code:
#include "main.h"
#include "view/videoplayerwindow.h"
#include <iostream>
#include <cerrno>
#include <QtGui/QApplication>
using std::cerr;
using std::endl;
int main(int argc, char *argv[])
{
_argc = argc;
_argv = argv;
if (argc < 3) {
cerr << "USAGE: " << argv[0] << " 127.0.0.1 12345" << endl;
exit(EXIT_FAILURE);
}
// Try to convert the port input into a number
uint16_t port = strtoul(argv[2], NULL, 10);
if (errno != 0 || port < 1) {
cerr << "Invalid port number. Quitting." << endl;
exit(EXIT_FAILURE);
}
return launchGUI(argv[1], port);
}
int launchGUI(char *ip, uint16_t port) {
try {
VideoPlayerWindow w(ip, port);
w.show();
return a.exec();
} catch (VideoStreamerCriticalException& ve) {
cerr << "A critical error occured with the video stream.\n -- " << ve << "\n\nThis program will now quit." << endl;
return 0;
}
}
where int _argc and char** _argv are defined in main.h.
Re: Memory corruption related to signal emission?
Ok. Now it could be good to see VideoPlayerWindow implementation (constructor, all methods called from constructor, and paintEvent implementation if there is one).
Re: Memory corruption related to signal emission?
Nothing fancy to see here.
Code:
VideoPlayerWindow
::VideoPlayerWindow(char *ip, uint16_t port,
QWidget *parent
) : _vss(ip, port)
{
setupGUI();
_vss.startReceiver();
}
void VideoPlayerWindow::setupGUI() {
// QMainWindow takes ownership of the widget, so no need
// to delete it.
_vpWidget = new VideoPlayerWidget(this);
setCentralWidget(_vpWidget);
connect(&_vss, SIGNAL(newStreamFound(VideoStream*)), _vpWidget, SLOT(addVideoStream(VideoStream*)));
}
with member variables
Code:
VideoPlayerWidget* _vpWidget;
VideoStreamerSession _vss;
VideoStreamerSession::startReceiver() starts an asynchronous receiver thread that processes incoming data related to streaming video.
I'd rather not post the entire program online, but if you need any more code I'll upload the project to temporary storage.
Re: Memory corruption related to signal emission?
Quote:
I'd rather not post the entire program online
I understand.
Does it crash if you do not startReceiver() ? You said that there are threads involved - to me its always first place to look for potential errors.
//edit: ok, probably there you have the "emit" statements. You may try to implement single-threaded version of the receiver, my bet is that threads are somehow responsible for the app crash.
Re: Memory corruption related to signal emission?
It does not crash if I don't call startReceiver(). But like I said here: if I remove these two signal emission commands (they're executed on the receiver thread, by the way) and still call startReceiver(), the program doesn't crash either. Even when no slots are connected to these signals, the mere emission of these signals causes a SIGSEGV somewhere else in the program. This leads me to believe it's not a thread safety issue but a memory corruption issue. I build with Qt 4.7.4, but any time I suspect an error is my code is caused by a Qt-related bug it turns out I'm wrong.
Re: Memory corruption related to signal emission?
I think its not possible to help you more without digging through the sources.
Its all up to your creative thinking now. You may try to create separate application, where you can test the VideoStream and VideoStreamerSession classes, without the gui layer. Or try to implement single-threaded version of receiver. Or try to allocate the _vss on heap (if you are out of ideas, why not try this).
Sorry, but without seeing the code, I can't help you more.
Re: Memory corruption related to signal emission?
Holy smokes... I just did some more digging and I found the culprit. I looked through all the "// TODO" comments in my code and then I remembered I had an odd issue with a signal/slot connection on a QTimer* that produced a warning in the debug output. The timer just wouldn't fire. I commented out the connect() command because I had more important things to do. When I came back to this snippet of code, I noticed that I hadn't initialized the QTimer*... I feel like crap for wasting your and my own time. Too bad Valgrind didn't detect this, because then the error would have been exposed much earlier.
Thanks for your help, though! :)