Qlist<QCameraInfo> causes access violation in QList destructor - c++

I am writing a video grabbing application in c++ using Qt5. I am following their example code and looking at the documentation for getting the camera info:
http://doc.qt.io/qt-5/qcamerainfo.html
The problem I have is that after I use the prescribed technique for getting camera data (which works perfectly):
QList<QCameraInfo>cameraInfos = QCameraInfo::availableCameras();
I get an Access violation error whenever cameraInfos goes out of scope.
For example, if I do:
void readDeviceInfo(void) {
// Camera devices:
QList<QCameraInfo>cameraInfos = QCameraInfo::availableCameras()
for (QList<QCameraInfo>::Iterator it = cameraInfos.begin();
it != cameraInfos.end(); ++it)
std::cout << it->description().toStdString().c_str() << std::endl;
}
The crash occurs on the return of this function. If I do:
foreach(const QCameraInfo &ci, QCameraInfo::availableCameras());
The crash occurs in the evaluation of the foreach loop. Likewise, if I declare QList<QCameraInfo> cameraInfos as a field in a class, the crash happens when the class is destroyed. This is verified by the output of my call stack:
ntdll.dll!000000007750eef1() Unknown
kernel32.dll!00000000773c1a0a() Unknown
> VideoCapture.exe!free(void * pBlock) Line 51 C
VideoCapture.exe!QCameraInfo::`scalar deleting destructor'(unsigned int) C++
VideoCapture.exe!QList<QCameraInfo>::node_destruct(QList<QCameraInfo>::Node * from, QList<QCameraInfo>::Node * to) Line 484 C++
VideoCapture.exe!QList<QCameraInfo>::dealloc(QListData::Data * data) Line 857 C++
VideoCapture.exe!QList<QCameraInfo>::~QList<QCameraInfo>() Line 817 C++
I am using Visual Studio 2013 (windows obviously).

You need to compile Qt yourself, then run your test case under a debugger and see where it crashes. You also need a minimal, self-contained test case for this - and that must be the part of the question (SSCCE). As it is, it's more likely that you're corrupting memory elsewhere and the failure you're seeing is the outcome of a corrupted heap, not a Qt bug.
Sidebar: You need to be proficient in running small examples in Qt Creator. Arguably, the templates Qt Creator comes with aren't very good for that. You can use this template, available as Other Projects->Simple qmake, to make quick prototypes.
The following works fine for me with 1 camera on current Qt on both OS X 10.9 and Windows 10/VS 2015. The std::cout you're using is red herring, you can use qDebug() as well.
// https://github.com/KubaO/stackoverflown/tree/master/questions/camlist-37603946
#include <QtWidgets>
#include <QtMultimedia>
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QComboBox combo;
QObject::connect(&combo, &QComboBox::currentTextChanged, [&]{
std::cout << combo.currentText().toStdString() << std::endl;
});
for (auto const & info : QCameraInfo::availableCameras())
combo.addItem(info.description());
combo.show();
return app.exec();
}

So after following Kuba's advice and running his test program in my environment with a freshly built Qt library, I got the same errors. Then I had the bright idea to run it in release mode rather than debug. Lo and behold, it worked perfectly, with both the freshly built Qt5 (x86, as it happened) and the pre-built binaries (64 bit) gotten from Qt's downloads page.
It seems that linking to the qt debug libraries was causing this behavior. I'm now linking to the non-debug libraries in debug mode and am nice and happy -- for the most part -- I am still a little annoyed that the qt libs suffixed with 'd' don't seem to work properly on my system. Nevertheless, I can move on with developing this project.
Thanks to all that commented and answered!

Related

How to fix processor affinity for Qt 5.9 Thread on Windows with Ryzen 7

I have been developing a program for my Master's Thesis with OpenSceneGraph-3.4.0 and GUI from Qt 5.9 (otherwise in Visual Studio 2015 and 2017). At work everything works fine, but now that I have a new Computer at home I tried to get it running.
However, when I call the frame() method for the viewer, I get a Read Access Violation in QtThread.cpp at the setProcessorAffinity(unsigned int cpunum), specifically in the following line:
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_prvData);
Here is the complete function (QtThread.cpp is part of OpenThreads of OSG):
// Description: set processor affinity for the thread
//
// Use: public
//
int Thread::setProcessorAffinity(unsigned int cpunum)
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_prvData);
pd->cpunum = cpunum;
if (!pd->isRunning) return 0;
// FIXME:
// Qt doesn't have a platform-independent thread affinity method at present.
// Does it automatically configure threads on different processors, or we have to do it ourselves?
return -1;
}
The viewer in OSG is set to osgViewer::Viewer::SingleThreaded, but if I remove that line I get an error "Cannot make QOpenGLContext current in a different thread" in GraphicsWindowQt.cpp(which is part of OsgQt), so that's probably a dead end.
Edit for clarification
I call frame()on the osgViewer::Viewer object.
In this function, the viewer calls realize() (which is a function of the Viewer class).
In there setUpThreading()is called (which is a function of the Viewer Base class).
This in turn calls OpenThreads::SetProcessorAffinityOfCurrentThread(0)
In there, the following code is executed:
Thread* thread = Thread::CurrentThread();
if (thread)
return thread->setProcessorAffinity(cpunum);
thread (after the first line) has a value 0x00000000fdfdfdfd which looks like an error to me.
In any case, the last call is the one I posted in my original question.
I don't even have an idea of where to start fixing this. I assume, it's some processor related problem. My processor is a Ryzen 7 1700 (at work it's an Intel i7 3770k), so maybe that helps.
Otherwise, at home I'm using Windows 10, wheras at work it's Windows 7.
I'd be thankful for any help at all.
So in the end, it seems to be a problem with OpenThreads (and thus the OpenSceneGraph part, which I can do nothing about). When using cmake for the OpenSceneGraph source, there is an option "BUILD_OPENTHREADS_WITH_QT" that needs to be disabled.
I found the solution in this thread in the OSG forum, so thanks to this guy.

How can I improve the startup time of Qt5 programs?

I recently switched to Qt5 and I noticed that initializing QApplication is taking noticeably longer (on the order of minutes) compared to Qt4.
Looking into it, the program seems to be spending its time here:
Qt5Guid.dll!QGlobalStatic<QFactoryLoader,&`anonymous namespace'::Q_QGS_directLoader::innerFunction,A0x95ca5a10::Q_QGS_directLoader::guard>::operator()() Line 129 C++
Qt5Guid.dll!QPlatformIntegrationFactory::create(const QString & platform, const QStringList & paramList, int & argc, char * * argv, const QString & platformPluginPath) Line 70 C++
Qt5Guid.dll!init_platform(const QString & pluginArgument, const QString & platformPluginPath, const QString & platformThemeName, int & argc, char * * argv) Line 1019 C++
Qt5Guid.dll!QGuiApplicationPrivate::createPlatformIntegration() Line 1176 C++
Qt5Guid.dll!QGuiApplicationPrivate::createEventDispatcher() Line 1196 C++
Qt5Widgetsd.dll!QApplicationPrivate::createEventDispatcher() Line 197 C++
Qt5Cored.dll!QCoreApplication::init() Line 769 C++
Qt5Cored.dll!QCoreApplication::QCoreApplication(QCoreApplicationPrivate & p) Line 689 C++
Qt5Guid.dll!QGuiApplication::QGuiApplication(QGuiApplicationPrivate & p) Line 570 C++
Qt5Widgetsd.dll!QApplication::QApplication(int & argc, char * * argv, int _internal) Line 569 C++
It's basically spending several minutes every startup initializing the windows platform plugin.
How can I reduce or remove this time and does anyone know what the cause might be?
I'm using Qt 5.5.1 with VS2012 64 bit.
Edit: Not sure if it's relevant, but I have QT_QPA_PLATFORM_PLUGIN_PATH="C:\Qt-5.5.1\plugins\platforms\" which is how it finds the platform plugin.
Edit2: Further investigation shows that the cause is that in the process of initializing the program, QFactoryLoader::update() scans through every file in some directories looking for a pattern. Because the directory includes the program directory it scans through the entirety of my program file (several gb).
The paths are determined by QCoreApplication::libraryPaths() which returns has 3 values:
C:/Qt-5.5.1/plugins/platforms
C:/Qt-5.5.1/plugins
C:/MyProject/x64/Debug <-- the problem
The update() function is called 7 times in the init process, but it's actually only the first two calls that are very slow.
I've also noticed that if I call QCoreApplication::libraryPaths() before the init, then only the first two paths are returned for the first 4 update() calls, which solves the problem.
It's great that I have a solution now, but I would like to understand why this works and find a less hacky one.
The answer without specific environment to quite a general question:
How can I improve the startup time of Qt5 programs?
... cannot really be given here. Most of Qt developers don't experience such delay. But we can always try to debug. So the answer is on how to debug. From what you posted the code is located at: qtbase/src/gui/kernel/qplatformintegrationfactory.cpp:
Qt5Guid.dll!QGlobalStatic<QFactoryLoader,&`anonymous namespace'::Q_QGS_directLoader::innerFunction,A0x95ca5a10::Q_QGS_directLoader::guard>::operator()() Line 129 C++
Qt5Guid.dll!QPlatformIntegrationFactory::create(const QString & platform, const QStringList & paramList, int & argc, char * * argv, const QString & platformPluginPath) Line 70 C++
It appears that the function called:
QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platform, const QStringList &paramList, int &argc, char **argv, const QString &platformPluginPath)
{
#ifndef QT_NO_LIBRARY
// Try loading the plugin from platformPluginPath first:
if (!platformPluginPath.isEmpty()) {
QCoreApplication::addLibraryPath(platformPluginPath);
if (QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))
return ret;
}
if (QPlatformIntegration *ret = loadIntegration(loader(), platform, paramList, argc, argv))
return ret;
#endif
return 0;
}
You can either point to debug version of Qt or load symbols for Qt5Guid.dll and make the Qt source code available to debugger and/or build Qt yourself at the machine you use for debugging of your project and link the executable with it. Then put a breakpoint on line 70:
if (QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))
And then run the program and investigate what prevents the plugin from being loaded quickly. From this context it is not even clear what exact plugin it is, either it comes with Qt or a custom one.
I would not start with the debugging (because, I would venture, you might have hit highly contested lock somewhere and debugging won't help much)
I would advise to start with good profiling of your code, and I know none better than tools/docs from Bruce Dawson
Start here and proceed with profiling your app
Short answer: Deploy your binary file into a subfolder.
Long answer: I had the very same issue and looking up the Qt source code, it will append the application directory in order to look up for plugins. So there is no choice but to leave the application alone in a folder unless someone do a merge request (if I have spare time, I will try to do it myself).

oracle::occi::ResultSet::next() crashes my program

I have a 64 bits C++ server application running on windows 7 and when it does a select on the database and calls next() on the result set the process simply dies, no exceptions, no dumps and no debug info after ResultSet->next(). Writes on the database works with no problems and both reads and writes works on the 32 bit version
I'm using the 11.2 version of the win64 oracle libraries that came with instant client and SDK
EDIT: it's the simplest of codes
const std::string sql("select * from schedule_import");
std::auto_ptr<IRecordSet> query = m_conn->Open(sql);
while(query->Next()) // dies
{
const std::string key(query->GetField("bean_key"));
//...
IRecordSet is just an interface for common functions of DB drivers like next, getField and it's implemented in here
bool OracleRecordSet::Next()
{
return m_pResultSet->next() != NULL; //crashes here
}
where m_pResultSet is a oracle::occi::ResultSet*
I'm not familiared with Oracle API, but question is if m_pResultSet is not NULL (in case of segmentation fault) and if there is no exception (in case of abort(), raise() stack).
BR!
After a lot of trys my problem is solved.
I was linking my debug program to oraocci11.lib because I didn't have the debug version and I thought it didn't matter much. After a bit of search I've found the debug version of the library, oraocci11d.lib, with the corresponding dll and the crash is gone

Using the IBM 3514 Borland Graphics Interface driver in High resolution mode in Turbo C++ on Windows 7 64 bit OS using DosBox

I'm running a graphical program in Turbo C++ using DosBox on Windows 7 64 bit. Now, I want to use the IBM3514 graphics driver in the High resolution mode (IBM3514HI). So, I wrote the following bare bones program to test it:
#include <graphics.h>
#include <iostream.h>
void main() {
int gd = IBM3514, gm = IBM3514HI, e;
initgraph(&gd, &gm, "C:\\TC\\BGI");
if (e = graphresult()) {
cout << grapherrormsg(e);
}
cleardevice();
rectangle(100, 100, 300, 300);
cin.get();
closegraph();
restorecrtmode();
}
Now, the program compiles and runs without any errors. However, the initgraph function call doesn't initialize graphics mode. The return value of graphresult is 0. Hence, no error has occurred. Yet, the program still runs in text mode. The blinking underscore is visible and the rectangle is not drawn.
I checked my C:\TC\BGI folder and the IMB3514.BGI file exists. Thus I assume that it does load the graphics driver. Yet, I can't figure out why the program doesn't execute in graphics mode, or even throw an error. However it works perfectly fine if I use the default settings: int gd = DETECT, gm;
Any explanation as to why my program doesn't work will be greatly appreciated. Please try to provide a fix to this problem. I would really like to draw on a 1024x768 screen with 256 colors.
Under Windows your graphical adaptor is virtualized. You can't access it directly and use its specific features (unless you use DirectX/OpenGL/other strange methods). DOSBox emulates some "historical" graphical adaptors for the programs it runs (to be precise: Tandy/Hercules/CGA/EGA/VGA/VESA). You must use the VESA 2.0 driver of TC (or in general the VESA driver).
The correctly name of the driver is ibm8514.bgi - not "3514" and not "imb" or so. But like my previous speaker said, better you use another driver. The best choice is to use the egavga.bgi driver of the Turbo resp. Borland C++ or Turbo Pascal package. Then you should compile them successful.
Expect you need a special feature of this driver. Then you must check them of this effort if you need them. I think the egavga.bgi, vesa or a directly switch to the graphic mode with some special routines to make graphic should work in DOSBox, EmuDOS or in all 32-Bit-Version of Windows like Windows XP or so.
Try this code instead:
int gd = 6, gm = 0, e;
(Both variables are INTEGERS, not STRINGS)

Crash in windows XP with very simple gtk+cairo program

I am developing a Gtk application using gtkmm on Windows Vista with Visual Studio 2005. The application works fine on the development machine but I have received crash reports after it has been run on Windows XP machines (both Service Pack 2 and 3). I distribute the app with the directory structure described in http://live.gnome.org/gtkmm/MSWindows and it had given me no problems so far.
The crash gives no error messages except for Windows asking whether I want to report the error.
In order to solve the problem, I tried to compile the program against different versions of gtkmm (a recent stable version gtkmm-win32-devel-2.16.0-4 and an older version gtkmm-win32-devel-2.10.11-1) but the problem persisted.
I hunted down the problem to a call to window->create_cairo_context() inside the on_expose_event of a Gtk::DrawingArea. When I commented out this call, the problem would disappear. So I wrote the following minimal program, which still crashes:
#include <gtkmm.h>
#include <iostream>
class MyWindow : public Gtk::Window {
bool on_expose_event(GdkEventExpose* event) {
std::cout << "expose" << std::endl;
Glib::RefPtr<Gdk::Window> window = get_window();
if(window) {
std::cout << "win" << std::endl;
std::cout << "Get cairo" << std::endl;
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
std::cout << "Get cairo done" << std::endl;
} else {
std::cout << "no win" << std::endl;
}
return true;
}
};
int main (int argc, char *argv[]) {
Gtk::Main m(argc,argv);
MyWindow w;
m.run(w);
return 0;
}
This minimal app may run and display the window without problem, but if I move the window off the screen limits or if I minimize/maximize it enough times (thus triggering calls to on_expose_event), it will eventually crash. It may also be the case that it won't crash the first time, but it will crash after restarting the app and triggering multiple calls to on_expose_event as described above. One thing I've noticed is that the app crashes after printing "Get cairo done". When I comment out the call to create_cairo_context, the problem dissapears, so I'm pretty sure there is something wrong with this line.
The error happens on clean installed Windows XP machines. I have tested both apps (original and minimal) on a colleague's notebook, which also has Windows XP, but it doesn't crash there. I suppose there is some dependency that is available/up to date in our computers but not in the computers where the application crashes. I have updated DirectX and installed Visual Studio C++ 2005 Redistributable on one of the problematic machines, but the problem persists.
The original app, which draws a graph on the DrawingArea, doesn't necessarily crash the first time either. It may work fine the first time after rebooting, but is more prone to fail the second time.
I am thinking about compiling and testing with MinGW to see if that solves the problem. I'll also try to compile a debug version and try to use a debugger. I have suspected the version of gdi32.dll might have something to do, seeing that libcairo-2.dll depends on this dll according to Dependency Walker, but until now it's just an speculation. Other than that, I'm out of ideas.
I'll be trying these ideas for the time being. Hopefully someone has more suggestions or knows what is going on with the code above.