Reputation: 53
I ran into this problem the other day - caught me by surprise and has halted my testing. I'm developing a feature outside of my normal application and I ran into an issue with a Q_PROPERTY that I can't seem to figure out. I've simplified the situation down to bare bones which still replicates the SIGSEGV. My code has a comment switch block that includes or removes an additional Q_PROPERTY "prop2" When I have just one property "prop1" I don't get the seg fault. When I add the additional property "prop2" I get the seg fault. I've included everything - including a dump of gdb. Any help/advice would be most appreciated.
System: Ubuntu 12.04 LTS (the greatest OS on Earth) Qt: 4.8 (as installed with apt-get install qt-sdk)
file: MyObject.hpp
#ifndef MYOBJECT_HPP
#define MYOBJECT_HPP
#include <QObject>
class MyObject : public QObject {
Q_OBJECT
Q_PROPERTY(QString prop1 READ prop1 WRITE setProp1 RESET resetProp1)
//* add/remove comment
Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2 RESET resetProp2)
// end */
private:
QString m_prop1;
//* add/remove comment
QString m_prop2;
// end */
public:
MyObject(QObject * parent = 0):QObject(parent){
resetProp1();
//* add/remove comment
resetProp2();
// end */
}
virtual ~MyObject(){ }
QString prop1() const{
return m_prop1;
}
QString setProp1(const QString& prop1){
m_prop1 = prop1;
}
void resetProp1(){
setProp1("reset");
}
//* add/remove comment
QString prop2() const{
return m_prop2;
}
QString setProp2(const QString& prop2){
m_prop2 = prop2;
}
void resetProp2(){
setProp2("reset");
}
// end */
};
#endif
file: main.cpp
#include <QApplication>
#include "MyObject.hpp"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyObject obj;
return app.exec();
}
file: CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(test)
find_package(Qt4 REQUIRED)
QT4_WRAP_CPP(test_MOC_SOURCES
MyObject.hpp
)
include(${QT_USE_FILE})
add_executable(test
main.cpp
${test_MOC_SOURCES}
)
target_link_libraries(test ${QT_LIBRARIES})
gdb output:
Reading symbols from /home/me/temp/string_seg_test/build/test...done.
(gdb) run
Starting program: /home/me/temp/string_seg_test/build/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffe7fc6700 (LWP 9297)]
[New Thread 0x7fffe77c5700 (LWP 9298)]
[New Thread 0x7fffe6354700 (LWP 9299)]
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6d00bbd in QString::operator=(QString const&) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
(gdb) bt
#0 0x00007ffff6d00bbd in QString::operator=(QString const&) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#1 0x0000000000401b43 in MyObject::setProp2 (this=0x7fffffffe11000, prop2=...)
at /home/me/temp/string_seg_test/src/MyObject.hpp:39
#2 0x0000000000401b7f in MyObject::resetProp2 (this=0x7fffffffe11000)
at /home/me/temp/string_seg_test/src/MyObject.hpp:42
#3 0x000000000040197b in MyObject::MyObject (this=0x7fffffffe11000, parent=0x0)
at /home/me/temp/string_seg_test/src/MyObject.hpp:21
#4 0x000000004017ee00 in ?? ()
#5 0x007fffffffe23800 in ?? ()
#6 0x0000010040154b00 in ?? ()
#7 0x000000004021b000 in ?? ()
#8 0x000000007ef92000 in ?? ()
#9 0x000000007ef9b000 in ?? ()
#10 0x0000000060310000 in ?? ()
#11 0x007ffff7d9a9d000 in ?? ()
#12 0x00000000604d2000 in ?? ()
#13 0x007fffffffe23000 in ?? ()
#14 0x0000000000000000 in ?? ()
(gdb)
Upvotes: 0
Views: 1112
Reputation: 98425
It's a simple problem. Your setter methods return QString
, but you never return anything from those methods. Thus a crash. The setters should have the following signature: void setPropx(const QString &);
Your compiler most likely has warned you about this. Thus, the lesson is: do not ignore compiler warnings. Understand their meaning.
On the other hand, you've left in a lot of irrelevant stuff. Had you been methodically stripping things line-by-line, you would have eventually arrived at a much smaller, single file example. The QObject
and application instances are not needed, neither is the indirection of the resetProp()
, nor do the getters make any difference.
The final two steps of minimization should have been:
// Step N-1
#include <QString>
class C {
QString m_prop1, m_prop2;
public:
C() { setProp1("reset"); setProp2("reset"); }
QString setProp1(const QString& prop1) { m_prop1 = prop1; }
QString setProp2(const QString& prop2) { m_prop2 = prop2; }
} c;
int main(int, char **) {
return 0;
}
// Step N
#include <QString>
class C {
QString m_prop1;
public:
C() { setProp1("reset"); setProp1("reset"); }
QString setProp1(const QString& prop1) { m_prop1 = prop1; }
} c;
int main(int, char **) {
return 0;
}
By this point you could have probably noticed what was wrong.
Everything should be in a single file. The separate header etc. are just a distraction that makes your question longer. This is what you should have posted :)
Upvotes: 1