Trouble prepending items to a QList
-
Hey there,
I have a QList called m_history that is a list of 'NBhistoryItems'. NBhistoryItem is a class I created that holds information such as url, date/time, and title. Whenever I call the slot addHistoryItem to prepend the NBhistoryItem to m_history it crashes. The crash report gives me this:
@0 @BUNDLEIDENTIFIER@ 0x0000000100017544 QList<NBhistoryItem>::prepend(NBhistoryItem const&) + 20 (qlist.h:546)
1 @BUNDLEIDENTIFIER@ 0x000000010001684f NBhistoryInterface::addHistoryItem(NBhistoryItem const&) + 47 @heres the slot:
@QList<NBhistoryItem> NBhistoryInterface::history()
{
return m_history;
}@and heres the NBhistoryItem class:
@NBhistoryItem::NBhistoryItem(QString hurl, const QDateTime &hdatetime, const QString &htitle)
{}@
Thanks for the help!
-
Hi
is
@
QList<NBhistoryItem> NBhistoryInterface::history()
{
return m_history;
}@Really the slot ?
-
Shoot I posted the wrong slot (how embarrassing :p)
Here is the correct slot:
@
void NBhistoryInterface::addHistoryItem(const NBhistoryItem& input)
{
m_history.prepend(input);
}
@m_history is the QList<NBhistoryItem>
So sorry for the confusion!
Thanks for your help!
-
Are you doing multi-thread access to that list ?
Also, the getter should be const
-
Using the const qualifier
What does a run through the debugger tells you about the crash ?
-
Here is the error:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 @BUNDLEIDENTIFIER@ 0x00000001000185a4 QList<NBhistoryItem>::prepend(NBhistoryItem const&) + 20 (qlist.h:546)
1 @BUNDLEIDENTIFIER@ 0x00000001000178af NBhistoryInterface::addHistoryItem(NBhistoryItem const&) + 47Ive done some research into getter/setter, but I'm still not sure exactly what that means. You told me the getter should be const. where is the getter in the code I provided?
Thanks!
-
the const qualifier looks like this, you just append it to the function signature:
@
QList<NBhistoryItem> NBhistoryInterface::history() const
{
return m_history;
}
@
that "const" means you are not changing the class members in that function, so the method can be called in a const context (e.g. other const functions might not call non-const functions on the same object etc). I guess there are better explanation but I hope that helps you :)Anyway can't you start your app in debug mode and get a stacktrace of the crash? the "error report" you provided is not helping much I guess :/
in the stacktrace you usually get a list of functions called when the crash happened and see exactly in what functions it crashes and where it was called from etc.Also keep in mind that with the call
@
m_history.prepend(input);
@
you object of type NBhistoryItem will be copied to the list (so the copy constructor of NBhistoryItem should be called), make sure that there is no problem with copying your class if you use pointers internally or whatever that might produce corrupt memory. -
NBhistoryItem has no pointers in it.
heres the class declaration:
@
NBhistoryItem::NBhistoryItem(QString hurl, const QDateTime &hdatetime, const QString &htitle)
{}
void NBhistoryItem::setUrl(QString input)
{
url = input;
}void NBhistoryItem::setTitle(QString input)
{
title = input;
}void NBhistoryItem::setDateTime(QDateTime input)
{
datetime = input;
}QString NBhistoryItem::returnUrl()
{
return url;
}QString NBhistoryItem::returnTitle()
{
return title;
}QDateTime NBhistoryItem::returnDateTime()
{
return datetime;
}
@@
class NBhistoryItem
{
public:
NBhistoryItem() {}
NBhistoryItem(QString hurl, const QDateTime &hdatetime, const QString &htitle);
void setUrl(QString input);
void setTitle(QString input);
void setDateTime(QDateTime input);
QString returnUrl();
QString returnTitle();
QDateTime returnDateTime();private:
QString url;
QString title;
QDateTime datetime;
};
@ -
I don't see the implementation of your empty constructor or did you just miss to copy that? :D
And I guess you need some c++ basics, getter methods shoudl always be const and parameters const& in most cases, e.g.@
// "const QString &input" instead of "QString input"
void NBhistoryItem::setTitle(const QString &input)
{
title = input;
}QString NBhistoryItem::returnTitle() const // add const qualifier here
{
return title;
}
@with Qt classes it's not that bad if you miss to use a reference (&) for the parameters because most Qt classes use implicit shared data, but you need to know if you just write "Class c" and not "Class &c" the copy constructor will be used and usually the whole data will be copied.
I understand that this is a major pitfall for c++ beginners because it's hard to know where to use references, pointers or even r-value references with c++11 (e.g. QString &&s).. because the compiler creates a default copy constructor for every class it may also be hard to see it it's actually used or not, I just told a colleague some days ago to just delete the copy constructor and then you will get a compiler error if you use it by accident :DJust a hint, you can delete the copy constructor like that (c++11):
@
NBhistoryItem(const NBhistoryItem &) = delete;
@
if you try to use it you see a compiler error with a message like "use of deleted function", in your case you might need it for the QList, just a general hint. I think Qt has some macros for deleting functions, too, But I am not sure exactly. -
Thanks for the primer! I studied basic C++ a while back before getting into Qt. In my craze to make awesome Qt GUI apps I've forgotten many of the basics. Time to review again!
So the copy constructor should be this?
@
NBhistoryItem(const NBhistoryItem &)
@Where would I place this in the .h file? right under the normal constructor?
How would I implement the copy constructor in this slot:
@
void NBhistoryInterface::addHistoryItem(const NBhistoryItem& input)
{
m_history.prepend(input);
}
@Thanks for the help! It really means a lot!
-
hey, sorry I might have confused you a little. :D
first, you don't need to implement your own copy constructor, you just have to know if you don't the compiler will generate a default one for you. I don't want to go into details here you can search the internet and look for "c++ copy constructor" or something, I'm sure you will find some stuff. :)
and with your addHistoryItem-slot there, you don't have to do anything I just wanted to let you know that the copy constructor will be used if you invoke "m_history.prepend(input);" inside of the QList class.
So that was just meant as some background info what happens if you add something to the QList it will be copied!sadly I have no idea why your app crashes.
-
Is it possible that the contents of NBhistoryItem cause some kind of data corruption and crash when its prepended (copied) to the list?
Here is the NBhistoryItem declaration:
@
class NBhistoryItem
{
public:
NBhistoryItem() {}
NBhistoryItem(QString hurl, const QDateTime &hdatetime, const QString &htitle);
void setUrl(QString input);
void setTitle(QString input);
void setDateTime(QDateTime input);
QString returnUrl();
QString returnTitle();
QDateTime returnDateTime();private:
QString url;
QString title;
QDateTime datetime;
};
@ -
I don't think that is related in your case and I asked you that before I've seen you class I think.
without your own copy constructor it will just copy the 3 members
@
QString url;
QString title;
QDateTime datetime;
@
and since you are using simple Qt classes and no pointers it should be fine. but as mentioned before I didn't see any implementation for the empty constructor. again did you just miss to copy that or is it missing (the linker should failed with that but you never know):
@
NBhistoryItem() {}
@
in your cpp file there was only the implementation for the 2nd constructor!? -
I do not have my own implementation of the copy constructor. I just want it to copy those 3 members, so shouldn't the default copy constructor be fine?
the .cpp has the implementation of the 1st constructor:
@
NBhistoryItem::NBhistoryItem(QString hurl, const QDateTime &hdatetime, const QString &htitle)
{}
@I have not implemented the 2nd constructor, I should probably delete it.
-
well THAT might be the problem all along, if you define 2 constructors you have to implement both of course! :D
But still the linker should throw an error if you don't, I have no clue why your can run the app like that :DAnd don't worry about the copy constructor.