Creation of QtChart object creates EXC_BAD_ACCESS error upon runtime - c++

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.

Related

Standalone FileDialog window with wxWidgets

I'm trying to use wxWidgets to create a open/save FileDialog window in a cross-platform way. So I've looked at the examples in the documentation. I also want to create standalone windows, with no parent, because I am not using any other instance of a wxApp/wxWindow elsewhere in my program.
Additionally, I need to have my own main function, so I don't want to use a macro such as IMPLEMENT_APP. I tried to follow the instructions given here, and came up with the following minimal program:
#include <wx/wx.h>
#include <string>
#include <iostream>
std::string openFile() {
wxFileDialog openFileDialog(NULL, _("Open XYZ file"), "", "",
"XYZ files (*.xyz)|*.xyz", wxFD_OPEN|wxFD_FILE_MUST_EXIST);
if (openFileDialog.Show() == wxID_CANCEL)
return ""; // the user changed idea...
// proceed loading the file chosen by the user;
return "something";
}
int main(int argc, char *argv[]) {
std::cout << wxEntryStart(argc, argv) << std::endl;
std::string s = openFile();
wxEntryCleanup();
}
And here is the CMakeLists.txt I used to compile the code:
CMake_Minimum_Required(VERSION 2.8.11)
Project(test)
Find_Package(wxWidgets REQUIRED)
Include(${wxWidgets_USE_FILE})
Add_Executable(test main.cpp)
Target_Link_Libraries(test ${wxWidgets_LIBRARIES})
Still, when I run this program, I get a Segmentation Fault, despite the wxEntryStart returning true, and I have no idea where the problem comes from. Any tip?
I wouldn't be so bold with stripping down wx's initialization code. It may work today, but in the next version, who knows...
This is what I use:
class MyApp : public wxApp { };
wxIMPLEMENT_APP_NO_MAIN(MyApp);
int main()
{
wxDISABLE_DEBUG_SUPPORT();
int dummy = 0;
if(!wxEntryStart(dummy, static_cast<wxChar**>(nullptr)))
return 1;
auto onx1 = on_exit([]{ wxEntryCleanup(); }); //using RAII for cleanup
//Other initialization, create main window, show it.
wxGetApp().OnRun(); //This starts the event loop.
//In your case, it looks like ShowModal's event loop is enough,
//so you don't need this.
}
I think those macros, ugly as they are, provide much better insulation against future changes in the library initialization code.
Ok, after some fiddling here is a code sample that works for me. Comments welcome on what'd be the best practices. What I did was keep ShowModal() instead of Show() in the openFile function. I also created the instance of singleton wxApp. The final code is here:
#include <wx/wx.h>
#include <string>
#include <iostream>
std::string openFile() {
wxFileDialog openFileDialog(NULL, _("Open XYZ file"), "", "",
"XYZ files (*.xyz)|*.xyz", wxFD_OPEN|wxFD_FILE_MUST_EXIST);
if (openFileDialog.ShowModal() == wxID_CANCEL)
return ""; // the user changed idea...
// proceed loading the file chosen by the user;
return "something";
}
int main(int argc, char *argv[]) {
wxApp::SetInstance( new wxApp() );
wxEntryStart(argc, argv);
std::string s = openFile();
wxEntryCleanup();
}
Not sure this is completely leak-free, as valgrind seems to complain a little after exit. Any tip about whether I could also put the wxEntryStart() in the openFile() function welcome (I am guaranteed that this is the only place where the wxWidgets lib is used, and I want an API as simple as possible).

Unable to make qmlRegisterType work

I've found some examples of qmlRegisterType on the internet but just can't make it work. I create a new Qt Quick 2 project and add the following contents:
This is my .pro file:
#Add more folders to ship with the application, here
folder_01.source = qml/testlib
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01
#Libraries
QT += core gui widgets
#Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =
#Header files
HEADERS += main.hpp
#The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp
#Installation path
#target.path =
#Please do not modify the following two lines. Required for deployment.
include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
qtcAddDeployment()
This is my code file (main.cpp):
#include <QtQml>
#include <QtWidgets/QApplication>
#include "qtquick2applicationviewer.h"
//test class
class TestClass:public QObject {
Q_OBJECT
public:
TestClass(QObject* parent=0):QObject(parent){}
public slots:
void test() {
qDebug("test!");
}
};
//entry point
int main(int argc, char *argv[]) {
//create application
QApplication app(argc, argv);
//register custom qml component
qmlRegisterType<TestClass>("testlib",1,0,"TestClass");
//create and show qml viewer
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/testlib/main.qml"));
viewer.showExpanded();
//back to OS
return app.exec();
}
This is my QML file (main.qml):
import QtQuick 2.0
import testlib 1.0
Rectangle {
TestClass {
id:testobj
}
Component.onCompleted: {
testobj.test();
}
}
But I face multiple linking errors:
undefined reference to `vtable for TestClass'
undefined reference to `TestClass::staticMetaObject'
undefined reference to `TestClass::metaObject() const'
undefined reference to `TestClass::qt_metacast(char const*)'
undefined reference to `TestClass::qt_metacall(QMetaObject::Call, int, void**)'
I'm using Qt 5.2.1 shipped with MinGW 4.8 stable. These errors mean the linker can not find library files which contain method implementations (stated above). What happened? May be fail to compile on Qt 5 but ok on Qt 4?
Notes about compilation with Qt:
(1) Use 'QT +=' in .pro file for Qt headers & Qt libraries
(2) Use 'HEADERS +=' and 'SOURCES +=' in .pro file for
project level headers and source codes
Notes about creating a custom QML component (herefrom called 'CustomCom'):
(1) Inherit publically 'CustomCom' from QQuickItem:
class CustomCom:public QQuickItem {}
(2) Put the Q_OBJECT macro right after first line of
class 'CustomCom' declaration.
(3) Inherit the constructor:
public: CustomCom(QQuickItem* parent=0):QQuickItem(parent){}
(4) Put the methods to be called by JS after "public slots:"
(5) Call 'qmlRegisterType' after creation of 'QApplication' and
before creating any QML view or viewer.
(6) IMPORTANT: If you fail to compile with error
'undefined reference to vtable...", just put the code of 'CustomCom.cpp'
nested inside the 'CustomCom.hpp' file, and put the whole code
of the class 'CustomCom.hpp' in the main header file because of
something wrong in header referencing.
Example header code:
[main.hpp]
class CustomCom:public QQuickItem {
Q_OBJECT
public:
CustomCom(QQuickItem* parent=0):QQuickItem(parent){}
public slots:
void test() {
qDebug("Test!");
}
};
Example source code:
[main.cpp]
int main(int argc,char** args) {
QApplication* app = new QApplication(argc,args);
//call before any qml may use the custom component
qmlRegisterType<CustomCom>("CustomLib",1,0,"CustomCom");
//class 'QtQuick2ApplicationViewer' is generated by Qt Creator
//when creating new Quick 2 project. The path to 'main.qml'
//may be different
QtQuick2ApplicationViewer* viewer = new QtQuick2ApplicationViewer();
viewer->setMainQmlFile("qml/project/main.qml");
viewer->showExpanded();
}
Example QML:
[main.qml]
import QtQuick 2.0
import CustomLib 1.0
Rectangle {
width:640; height:360;
CustomCom {
id:customcom;
}
Component.onCompleted: {
customcom.test();
}
}
Solution to the question (facing 'Undefined reference to vtable'):
Combine 'TestClass.hpp' & 'TestClass.cpp' into 'TestClass.hpp' file
Move the content of 'TestClass.hpp' to 'main.hpp'
The problem was caused by using master header file. Putting the #include(s) only when needed solves the problem.
First you don't call parent contructor
TestClass::TestClass():QObject(0) {
}
or better
TestClass::TestClass(QObject* parent=0):
QObject (parent) {
}
Second where are you calling the qmlRegister? If am I right you need to register type before you use it, so before QQmlEngine load source codes of qml file.
I got the same problem and got it resolved by just add the header file (TestClass.hpp in your case) into the .pro file like this:
HEADERS += TestClass.hpp
It will guarantee moc will find it. And by the way, .h files are also OK.

Why doesn't my QDeclarativeItem get any mouse/keyboard events?

This is a reduced down, minimum complete example demonstrating my problem:
I have an application which hosts a QDeclarativeView; file events.cpp:
#include <QApplication>
#include <QDeclarativeView>
#include "TestItem.h"
int main(int argc,char* argv[]) {
QApplication app(argc,argv);
qmlRegisterType<TestItem>("Testing",1,0,"Tester");
QDeclarativeView page;
page.setSource(QUrl("page.qml"));
Q_ASSERT(page.status()==QDeclarativeView::Ready);
page.show();
return app.exec();
}
That TestItem is a subclassed QDeclarativeItem defined in file TestItem.h:
#ifndef _TestItem_h_
#define _TestItem_h_
#include <iostream>
#include <QDeclarativeItem>
#include <QPainter>
class TestItem : public QDeclarativeItem {
Q_OBJECT
public:
TestItem() {
setFlag(QGraphicsItem::ItemHasNoContents,false);
std::cerr << "[TestItem created]";
}
void paint(QPainter* painter,const QStyleOptionGraphicsItem*,QWidget*) {
painter->drawLine(0,0,width(),height());
painter->drawLine(0,height(),width(),0);
}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent*) {
std::cerr << "[TestItem::mousePressEvent]";
}
void keyPressEvent(QKeyEvent*) {
std::cerr << "[TestItem::keyPressEvent]";
}
};
#endif
and the page.qml file loaded into the QDeclarativeView is simply:
import QtQuick 1.0
import Testing 1.0
Tester {
width: 200
height: 200
}
It's all built (with Qt 4.8 on Debian-Wheezy amd64) with qmake file
CONFIG += debug
QT += core gui declarative
TARGET = events
TEMPLATE = app
SOURCES += events.cpp
HEADERS += TestItem.h
and, once built, when I run ./events I get a window displaying the Tester's painted 'X', as expected:
and a [TestItem created] logged to the console. However, clicking within the window or pressing keys completely fails to invoke either of the mouse or key event handlers.
I'm completely mystified. Is some extra magic (in the C++ or QML domains) needed to get mouse/keyboard events routed to these sort of "plugin" QDeclarativeItem classes? I certainly don't have any problems defining a MouseArea in the QML file and having it do stuff to QML state, and the code this is reduced from has no problems with signals and slots interoperating between the C++ item and QML code... but when it comes to mouse/keyboard events, there's just no sign of them on the C++ side.
To get (left) mouse events, all that is needed is to add
setAcceptedMouseButtons(Qt::LeftButton);
in the TestItem constructor. This is a little surprising as the documentation for the inherited QGraphicsItem::setAcceptedMouseButtons says "By default, all mouse buttons are accepted", but maybe something else in the setup messes with the state.
To get keyboard events, setFocus(true) just needs to be invoked. The documentation seems to imply setFlag(QGraphicsItem::ItemIsFocusable,true) should also be called, but it doesn't actually seem to be necessary in my test.

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?

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

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);