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 QMetaObject

    I 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!)



  • @Jeff-Andle

    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.