Qt5.3.2 QList losing QString contents between assignment and use
-
I am working with SmtpClient for Qt, Copyright (c) 2011-2012 - Tőkés Attila
I am using QtCreator under Ubuntu.
The code is creating "To" structures and adding them to a QList. To goes out of scope and is no longer valid, so if the QList is only making a list of pointers, then the behavior makes sense. On the other hand, this is code that supposedly worker (under Qt 4.8?; possibly not Ubuntu), so it must just be a matter of forcing a deeper copy. Suggestions?The code has a class, EmailAddress, which has private members:
QString name;
QString address;The code defines a list of recipients:
QList<EmailAddress*> recipientsTo, recipientsCc, recipientsBcc;I am adding recipients (only one for now). I tried creating "to" from two Qstrings. In an attempt to fix the issue I am having, I also tried using char [idx][128] (as below) to initialize with the same effect. My calling code uses:
int idx; for (idx=0; idx<mp.nRecpt; idx++) { EmailAddress to(mp.RcptAddr[idx] , mp.RcptName[idx]); message.addTo(&to); }
NOTE: to loses scope here and the only reason I still see values in message is probably that nothing has overwritten the ghost of the values on the stack yet. The called library uses:
void MimeMessage::addTo(EmailAddress* rcpt) {
this->recipientsTo << rcpt;
}After this call the debugger shows the correct strings in "this" (message) for address and name. Inside the loop - where "to" is still in scope - I see:
Locals
...
message @0xbff07efc MimeMessage
...
recipientsTo <1 items> QList<EmailAddress*>
[0] @0xbff07fe0 EmailAddress
[QObject] @0xbff07fe0 QObject
[methods] <0 items>
[properties] <more than 0 items>
[signals] <0 items>
address "jandle@..." QString
name "Jeff ..." QString
staticMetaObject @0xb7741a3c QMetaObject
sender @0xbff07eec EmailAddress
subject "" QString
...
to @0xbff07fe0 EmailAddress
[QObject] @0xbff07fe0 QObject
[methods] <0 items>
[properties] <more than 0 items>
[signals] <0 items>
address "jandle@..." QString
name "Jeff ..." QString
staticMetaObject @0xb7741a3c QMetaObjectI perform a few more assignments to message, after which the fields in message are still valid. As I said above, I am guessing it's just that "to" is still on the stack even if it went out of scope, since "to" is no longer in the Locals list. Then I execute the calls to send the email.
// Now the email can be sent if (!smtp.connectToHost()) { qDebug() << "Failed to connect to host!" << endl; return -1; } if (!smtp.login()) { qDebug() << "Failed to login!" << endl; return -2; } if (!smtp.sendMail(message)) { qDebug() << "Failed to send mail!" << endl; return -3; } smtp.quit(); return 0;
After smtp.connectToHost() the recipient fields are no longer valid. I am guessing this is because the function call used the stack and wiped out "to". This makes me thing I just need a deeper copy on QList<>.
Locals message @0xbff07efc MimeMessage
...
recipientsTo <1 items> QList<EmailAddress*>
[0] @0xbff07fe0 EmailAddress
[QObject] @0xbff07fe0 QObject
[methods] <0 items>
[properties] <more than 0 items>
[signals] <0 items>
address <not accessible> QString
name <not accessible> QString
staticMetaObject @0xb7741a3c QMetaObject -
int idx;
for (idx=0; idx<mp.nRecpt; idx++)
{
EmailAddress to(mp.RcptAddr[idx] , mp.RcptName[idx]);
message.addTo(&to);
}Object "to" is local to the loop, so when the end of the loop is reached, the destructor gets called and data is undefined.
This shall work …
int idx;
for (idx=0; idx<mp.nRecpt; idx++)
{
EmailAddress *to = new EmailAddress(mp.RcptAddr[idx] , mp.RcptName[idx]);
message.addTo( to);
} -
Thanks. I wasn't sure if QList made copies of data or copies of pointers. This is the sort of thing I assumed it was. Of course this code will ultimately run on an embedded system for indefinite periods, so i was hoping to let Qt do my memory clean up.
if I use "new" for *to is added to the QList, I assume I have to walk the list and delete all of them after sending the email (certainly not after assigning them!)
-
If you do not like that cleanup or if it is too hard to decide whether to free the memory you can use one oft these.
QSharedData QSharedDataPointer QSharedPointer
I have used QSharedDataPointer (but not the others so far), and it seems to work nice.