Important: Please read the Qt Code of Conduct -

Copying struct which includes QString

  • Hello,

    I have some strange behavior.
    I am trying to copy struct between classes :

    typedef struct _mystruct
    QString mystr;
    int myint;

    mystruct src_struct;

    but I then see that the recieving class have all the struct elements correcly except the QString which is undefined.
    When I created the src_struct as private in that class, then everything works OK.
    It seems as if created the src_struct as stack variable, results in loss of QString.
    But I don't understand why, if there is a memcpy of the whole struct.

    Thank you.

  • Moderators

    Using memcpy you can only copy PODs. QString is not a POD.
    To simpify you can think of it like this:

    class QString
       QChar* data;
       int size;

    That's not what it actually looks like but conceptually this is it. As you can see copying it with memcpy would be an error, because you're just copying a pointer and not the data itself. Paired with the fact that QString is implicitly shared copying it with anything but its copy constructor or assignment operator is an undefined behavior almost certainly leading to crash. It doesn't matter if the string is allocated on the stack or heap. It has a pointer to implicitly shared data on the heap.

  • @Chris-Kawa

    I have also tried to copy the same struct with = operator and got the same behaviour.

    copy_func(mystruct& src_str)
    this->dst_str = src_str;

    I understand from your answer that I must copy (each of the) QString in struct separately.
    I wander why it did work when I just changed from local variable to proivate variable in class.
    Does it mean it was just "lucky" ?


  • Moderators

    @ranshalit said:

    I understand from your answer that I must copy (each of the) QString in struct separately.

    No, you shouldn't have to write that yourself. This should happen with the compiler generated copy constructor and assignment operators. These functions do memberwise copy using their copy constructors and assignment operators.

    Your last example should work. Can you show the actual code? Maybe there's something else going on.

    Does it mean it was just "lucky" ?

    Not at all. It was just as broken, just hidden better. When you memcpy a local QString it falls apart just as soon as that string goes out of that local scope, because it deletes the underlying data and leaves the copied object in undefined state. When changing that to a member variable the copied objects is "fine" (well not really, but it might "survive" to some degree) as long as the whole class instance exists. As soon as the class instance is destroyed the member is destroyed too, so you're back to the same problem, it just happens later than with the local variable. In both cases if you try to write to any of these objects you make garbage out of both, because the internal refcount and shared data information will be totally whacked.

Log in to reply