Qt: MainWindow->show() crashes program on call - c++

I've been working on this program using Qt in c++ and so far so good. However I then needed to get this program moved to another machine. I have subversion, so I committed every file in the project folder and checked it out on the new machine. After jumping through some hoops to get it to successfully build and running, I get this error:
ASSERT: "dst.depth() == 32" in file qgl.cpp,.
invalid parameter passed to c runtime function qt
I tried stepping through the program to find the point where it crashes and found that it was after everything had been initialized and show() is called for the class that inherits the QMainWindow class. The c->showView() line calls QMianWindow->show().
----------main.cpp------------
#include <QApplication>
#include "ModelI.h"
#include "ControllerI.h"
#include "Model.h"
#include "Controller.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ModelI *m = new Model();
ControllerI *c = new Controller(m);
c->showView(); <- ERROR HERE
return a.exec();
}
The confusing part of the problem is that the program works perfectly fine on my machine when show() is called. I don't know what could be different between the two machines to make the program behave so differently. Both use the same version of Qt (SDK 2010.05). Both are developing with Eclipse. The only difference I can find is that my compiler is MinGW 4.5.0 and the other machine's is MinGW 4.5.2.
EDIT 1:
This is what Controller::showView() looks like.
void Controller::showView()
{
mView->show();
}
And this is how mView is initialized.
mView = new View(mModel, this);

Related

Creation of QtChart object creates EXC_BAD_ACCESS error upon runtime

I currently trying to move some code from Python to C++ for practice reasons and tried to create a line chart with the QtCharts library.
I installed the Qt library with the Qt open source installer provided by Qt on their website and finally managed to include the library in the project on Clion with the following code:
CMakelist.txt
cmake_minimum_required(VERSION 3.12)
project(Uebung1)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Qt
# Set this to your Qt installation
set(CMAKE_PREFIX_PATH /Users/DaniBook/Qt/5.11.2/clang_64)
set(RESOURCE_FOLDER res)
set(RESOURCE_FILES ${RESOURCE_FOLDER}/resources.qrc)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5Charts CONFIG REQUIRED)
set(PROJECT_SOURCE_DIR src/)
include_directories(${PROJECT_SOURCE_DIR})
add_executable(Uebung1 src/main.cpp src/tools.h src/tools.cpp)
target_link_libraries(Uebung1 Qt5::Charts)
So far so good I was able to then use the library in my code which basically consists of a two functions. One that reads data from a file and converts it to a vector of integers and one that takes this vector and attempts to create a Qt line chart.
tools.cpp
#include "tools.h"
#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <QtCharts>
#include <fstream>
using namespace std;
void GC_skew(vector<long> &gc_data, string &genome_file) {
ifstream gfile(genome_file);
string line;
long g_sum = 0, c_sum = 0;
if(gfile.is_open()) {
//reading file line by line
while(getline(gfile, line)) {
//iterating over string characters to count G and C
for(auto &character : line) {
switch(character) {
case 'G' :
g_sum++;
break;
case 'C' :
c_sum++;
break;
default :
continue;
}
//appending skew to vector
gc_data.push_back(g_sum - c_sum);
}
}
}
else {
cout << "Unable to open file!" << endl;
}
}
void skew_chart(vector<long> &gc_data) {
auto *series = new QLineSeries();//creating new series object
auto *chart = new QChart(); //creating new chart object
auto *chartview = new QChartView(chart); //creating chartview object
QMainWindow window; //window object for display
long pos = 0;
//iterating over the vector and appending data to series
for(auto it : gc_data) {
series->append(pos, it);
pos++;
}
//adding series to chart and viewing chart
chart->addSeries(series);
chartview->setRenderHint(QPainter::Antialiasing);
window.setCentralWidget(chartview);
window.show();
}
main.cpp
#include <iostream>
#include "tools.h"
#include <vector>
#include <map>
using namespace std;
int main() {
vector<long> gc_data = {};
string genome_file = "<path_to_file>";
GC_skew(gc_data, genome_file);
skew_chart(gc_data);
}
The code compiles without an error but when running it terminates with exit code 11 (whatever that means). However, upon debugging I figured there is a problem with the creation of a new QChart object where I keep getting the following exception as stated by the debugger:
Exception = error: use of undeclared identifier 'Exception' //occurs somewhere before the one below but does not effect the application
Exception = EXC_BAD_ACCESS (code=1, address=0x0) //causes the application to crash
Debug information
The way of initialization above is exactly the way given by Qt (https://doc.qt.io/qt-5/qtcharts-linechart-example.html) additional research in their resources did not lead to any solution. Does anybody of you might know what to do?
P.S.: by stepping through the lines one by one I discovered a jump upon initialization into a header which seems to define an exception which is raised at whatever event
qtflags.h (part of Qt lib)
Q_DECL_CONSTEXPR inline QFlags(Zero = Q_NULLPTR) Q_DECL_NOTHROW : i(0) {}
however the stack trace of the debugger indicates a successful object creation.
stack trace of debugger
The Qt version is 5.11.2
Compiler version Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Thanks in advance if anybody can make sense of this
You dont have any QApplication instance.
Here's a quote from Qt Docs:
The QApplication class manages the GUI application's control flow and
main settings.
QApplication contains the main event loop, where all events from the
window system and other sources are processed and dispatched. It also
handles the application's initialization, finalization, and provides
session management. In addition, QApplication handles most of the
system-wide and application-wide settings.
For any GUI application using Qt, there is precisely one QApplication
object, no matter whether the application has 0, 1, 2 or more windows
at any given time. For non-GUI Qt applications, use QCoreApplication
instead, as it does not depend on the QtGui library.
The QApplication object is accessible through the instance() function
that returns a pointer equivalent to the global qApp pointer.
So, the line
QApplication app(argc, argv);
creates an instance of the QApplication class.
In the end you need to call app.exec() which enters the main event loop and waits until exit() is called, then returns the value that was set to exit() (which is 0 if exit() is called via quit()).
It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets.

QT 5.6.1 app crashes after exiting slot only on x86 arch but not x64

I am facing an issue that i cannot understand and i need your lights. I have found no answers on my problem on others topics yet.
Context :
I am using QT 5.6.1 compiled dynamically (x86 and x64) on a Windows 10 x64.
Problem :
I have made a basic program compiled twice (x86 and x64) that just display a Window with a button and connects the button to the "clicked" signal. My Window is correctly displayed but when i hit my button to fire signal the app crashed just after exiting the SLOT connected to the SIGNAL (qDebug is correctly called from the slot). But i am only facing this issue with x86 QT dll's...
Here is the code:
.cpp:
MyWidget::MyWidget()
{
QMainWindow *pqMainWindow= new QMainWindow(this);
QPushButton *pqButton= new QPushButton("MyButton");
/* Setting up the window */
pqMainWindow->setWindowModality(Qt::WindowModal);
pqMainWindow->setGeometry(geometry());
pqMainWindow->move(QPoint(100, 100));
/* Connecting signal clicked to slot */
QObject::connect(pqButton, SIGNAL(clicked(bool)), this, SLOT(_onMyActionTriggered(bool)));
pqMainWindow->setCentralWidget(pqButton);
/* Showing the window */
pqMainWindow->show();
}
MyWidget::~MyWidget()
{
/* Nothing to do yet */
}
void MyWidget::_onMyActionTriggered(bool bValue)
{
qDebug("Slot <_onMyActionTriggered> called");
}
int __cdecl main(int argc, char **argv)
{
QApplication qapp(argc, argv);
MyWidget widget;
return qapp.exec();
}
.h
class MyWidget: public QWidget
{
Q_OBJECT;
public:
MyWidget();
virtual ~MyWidget();
private slots:
void _onMyActionTriggered(bool bValue);
private:
};
Here is the call trace :
Qt5Widgets!QAction::activate+0x103
Qt5Widgets!QToolButton::nextCheckState+0x1a
Qt5Widgets!QAbstractButton::click+0x103
Qt5Widgets!QAbstractButton::mouseReleaseEvent+0x7e
Qt5Widgets!QToolButton::mouseReleaseEvent+0xd
Qt5Widgets!QWidget::event+0xa8
Qt5Widgets!QSizePolicy::QSizePolicy+0x83b
Qt5Core!QCoreApplication::translate+0x30f56
Qt5Gui!QGuiApplicationPrivate::processMouseEvent+0x6c1
USER32!SetManipulationInputTarget+0x53
USER32!DispatchMessageW+0x251
USER32!DispatchMessageW+0x10
qwindows!qt_plugin_query_metadata+0x2065
Qt5Core!QCoreApplication::exec+0x160
qt_auth_test!wmain+0x7c
qt_auth_test!QObject::event+0xb5
KERNEL32!BaseThreadInitThunk+0x24
ntdll!RtlUnicodeStringToInteger+0x21e
ntdll!RtlCaptureContext+0xe1
I have compiled QT myself but i have the same result when using dll and lib downloaded on QT Website.
Thanks everyone for your help, i've finally found the issue.
Here is the answer :
My program uses the stdcall (/Gz) convention but QT uses cdecl (/Gd). The generated moc file was compiled with the stdcall convention and this is what caused the issue (stack problem when releasing parameters because of different convention between callee and caller).
Now my program is compiled using the stdcall convention (because it is mandatory for me) BUT the generated moc files are compiled with cdecl and i have set the __cdecl keyword on my private slots headers! Now It works perfectly!
Once again, thank for your time. I hope this topic will help someone one day with a similar issue.
Setting window modality on a child of a hidden widget makes no sense. Perhaps that's a problem. Try the following, and check if/when it crashes. There definitely is a Qt 5.6 bug on OS X at least: when the button's modality is reverted, the widget still doesn't receive input and you must exit the application by other means.
#include <QtWidgets>
int main(int argc, char **argv)
{
int n = 0;
QApplication app{argc, argv};
QPushButton widget{"Widget"};
QPushButton button{"Button", &widget};
button.setWindowFlags(Qt::Window);
QObject::connect(&button, &QPushButton::clicked, [&]{
button.setText(button.text().append("."));
++n;
if (n == 5) {
button.setWindowModality(Qt::WindowModal);
button.hide();
button.show();
}
else if (n == 10) {
button.setWindowModality(Qt::NonModal);
button.hide();
button.show();
}
else if (n == 15)
app.quit();
});
button.move(widget.geometry().bottomRight());
widget.show();
button.show();
return app.exec();
}

QTGraphicsView allways instantly closes after running outside from main method

I want to create a file that contains and manages the entire UI outside of the main.cpp and its main function.
To start I used the code from this answer, which worked fine
from inside the main method.
To prevent information loss I show the code below as well:
#include ...
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsPixmapItem item(QPixmap("c:\\test.png"));
scene.addItem(&item);
view.show();
return a.exec();
}
I tried to outsource this code into an own
class, but after executing the shown code the just created window
disappeared again within a few milliseconds without a warning or an error.
To check if I made a mistake within my own class I tried to use this code
from an own function within my main.cpp
void initUI(QApplication * application){
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsPixmapItem item(QPixmap(application->applicationDirPath() + "\\graphics\\Theme1\\background.png"));
scene.addItem(&item);
view.show();
}
But the same problem ocurs here. Why does the shown code needs to be executed within the main method, and how could you outsource it?
In case this information helps: I'm running on windows with Qt Creator 3.6.1
based on Qt 5.6.0 (MSVC 2013, 32 bit)
Edit:
Here is my main method
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
initUI(&a);
return a.exec();
}
Edit 2:
The error does not occur when I add an
application->exec();
Can somebody explain why this happens? What is the difference between
the call of application->exec() in the initUI-method and the a.exec() call
within the main method?
The destructors of scene and view are called once you exit initUI, as it is put on the stack. You need to put it on the heap in order to survive after exiting the init function. Of course you should take care of dangling pointers.

Crash with QItemSelectionModel::selectedIndexes()

I've been searching all around for a solution to this problem and I'm starting to believe this can be a bug in the Qt function itself.
The problem is that after you call QItemSelectionModel::selectedIndexes() the program will crash when the program tries to destruct the QModelIndexList that this function returns. Before the crash, you get the following debug message:
Debug Assertion Failed!
(…)
File:
f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line:1419
Expression:
_pFirstBlock == pHead
(…)
Here is the simplest code that will cause the problem, so you can test it by yourself:
#include <QApplication>
#include <QStringList>
#include <QStringListModel>
#include <QItemSelectionModel>
#include <QModelIndex>
#include <QModelIndexList>
#include <QListView>
#include <QItemSelectionModel>
void doSomethingWithSelection(QItemSelectionModel* selectionmodel);
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList list;
list.push_back("1");
list.push_back("2");
list.push_back("3");
list.push_back("4");
QStringListModel model(list);
QListView view;
view.setModel(&model);
view.setSelectionMode(QAbstractItemView::ExtendedSelection);
QItemSelectionModel *selectionmodel = view.selectionModel();
QModelIndex first = model.index(0);
QModelIndex last = model.index(2);
QItemSelection selection(first, last);
selectionmodel->select(selection,QItemSelectionModel::Select);
doSomethingWithSelection(selectionmodel);
view.show();
return a.exec();
}
void doSomethingWithSelection(QItemSelectionModel* selectionmodel)
{
QModelIndexList indexlist = selectionmodel->selectedIndexes();
// this is what causes the error. I put this inside a function
// so the error will happen when exiting the function,
// when the program try to destroy the list nodes.
}
I have the exact same problem only that I am using selected rows instead of selected indexes. I narrowed it down to function exit when the internal QList in QModelIndexList tries to delete the indexes from the heap. Not sure how to fix it but I read this interesting post here and came up with this function:
QModelIndexList Class::getViewSelection(QAbstractItemView *view , int columnNumber) const
{
QModelIndexList list;
for (int row = 0; row < view->model()->rowCount(view->rootIndex()); ++row)
{
QModelIndex index = view->model()->index(row, columnNumber, view->rootIndex());
if (view->selectionModel()->isSelected(index))
list.push_back(index);
}
return list;
}
I wrote this function to get selected rows so the column parameter is the column you want the index for.
I had the same problem with QTreeView and accessing selectedIndexes() or anything in selectionModel().
It was fixed when I used the correct /MD compiler switch with the correct Qt libraries.
To fix the crash:
compile your code with /MDd and link with debug Qt libs (example Qt5Cored.lib
compile your code with /MD and link with release Qt libs (example Qt5Core.lib)
I managed to solve the problem, but right now I don’t understande why this works, yet: (I'm writing this as an answer hoping that it can help someone with the same problem)
In my Qt project, I was using a Kit with Microsoft Windows SDK for Windows 7 (7.0.7600.16385.40715) (x86) as compiler. When I changed the compiler to Microsoft Visual C++ Compiler 10.0 (x86) this code worked correctly.
As I said, I don't know why this works and if someone can explain this to me I will be happy to hear. I don't know even why Windows SDK is listed as a compiler.. it is not, is it?

Running a C++ Qt application through a boost python module

Is it possible to run a Qt gui application as a boost module through python? It was working as a standard C++ executable, but now I'm compiling it down to a shared library and trying to launch it from python. Right now it just goes into the python interpreter every time I run simpleMain() from the interpreter. As in, I get a new "Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)" greetings every time and my program segfaults when I close the interpreter. Also, I can't call the main function directly because I'm not sure how to convert a python list to a char*. A string to char seems to wrok naturally.
This is my python code to launch it:
import libsunshine
libsunshine.simpleMain()
and here's my C++ code:
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(libsunshine)
{
def("say_hello", say_hello);
def("simpleMain", simpleMain);
def("main", main);
}
int simpleMain()
{
char* args[] = {};
main(0,args);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Sunshine w;
w.show();
return a.exec();
}
You can write your application setup in PyQt, which is as simple as
import sys
from PyQt4 import QtGui
QtGui.QApplication(sys.argv)
at the beginning of your script. Then can call c++ code in your modules which can open/close/... windows. (I have code which works this way)
I think it is illegal to call main in c++, which might be perhaps the reason for segfault.
Hmm usually main is called with
argc == 1
even when there are no params, argc[0] being the executable name.
Also argv is expected to be a list of pointers to strings terminated with a null pointer, while you're passing nothing. Depending on how QApplication parses the argument list (it may loop depending on argc, or it may just look for a null pointer), it can crash if passed even an argc of zero.
Try
char *args[1] = { NULL }; main(0, args);
or
char *args[2] = { "Dummy name", NULL }; main(1, args);