Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Random crash with QVector



  • I got some random crashes, when i use QVector, for unknown reason.
    So when i do this:

    QVector<int> data;
    int a = 120;
    int b = 546;
    int c = 157;
    data.append(a);
    data.append(b);
    data.append(c);

    Now, here the problem starts. I want to set the pointer, to the internal element of QVector. So:

    int* p = &data[0];

    Now, for some reasons, it does work at the beginning, but after just few elements added, it stops. The pointer gets changed from what i was able to see, so i fixed this by using a pointer to another pointer.

    What is the reason of that? Also, i want to make sure, that this fix for this issue, is safe, that it's not gonna crash anymore.



  • The address of the first element is going to change as you "append" elements and it has to reallocate memory to allow for a larger continguous space.

    Never expect that &data[0] is constant. A resize(), either explicit or implicit MAY cause a reallocation and invalidate the saved address of the first element.


  • Moderators

    @Loc888 Can you please explain your goal? Why do you want the pointer to an internal element of QVector?



  • @JKSH Because i want to point to the data.. There are objects and things happening to them, so i want those things to happen only at the selected object. Because the objects are added dynamically, i had to use vector, and yes i know i could use pointers in the vector, but because i already program it for non-pointer vector, i choose that instead of changing it, i will simply just use pointer to the direct data.


  • Lifetime Qt Champion

    @Loc888 As @Kent-Dorfman pointed out if you add data then QVector will sometimes reallocate memory and move vector data into new memory to resize the vector. So, all pointers will become invalid.
    Instead of using pointers, why don't you use indexes inside the vector? The indexes will not change as the elements do not change their position inside vector.



  • @jsulm What you mean by indexes?


  • Lifetime Qt Champion

    @Loc888

    data[0]; // 0 is the index in the vector
    


  • Please have a look

        QVector<int> aVector;
        aVector.push_back(254);
        int *p= &aVector.data()[0];
        *p= 123;
        qDebug() << aVector.at(0);
    
    

    The output is 123 so in order to get the pointer to a specific QVector element please use

    &aVector.data()[x]
    


  • In defense of the OP, there are valid reasons for getting the address of the first element. You just need to treat it as a temporary, and understand that any operation that modifies the size of the vector may invalidate it so DONT SAVE IT. REREAD IT when necessary....and data() is just an alias for &data[0] with the perk of possibly being const, but I'm not gonna touch the whole "what is const" discussion.



  • @jsulm I can't do that, because the data what i use, is not declared there. I didn't want to give a pointer to the whole vector, because it will just create some mess.

    Each object from class A, have the data for class B, which is just the display class of a particular object inside the vector. Class B is also a vector. If i pass the whole vector pointer, then i will have to specifie which index of A belongs to the index of B.

    Basically it's just few lines of code, to send the a pointer to b. I wanted to split the data from the UI, so that's why they are not inside 1 class.



  • @Loc888 so pass around a reference to the whole container and then pull the data from it using the indexes, whenever you need to, and for whatever range suits your fancy. With the minimal information you've shared, my spidey-sense tells me you are over-thingking your problem.


  • Lifetime Qt Champion

    @Loc888 said in Random crash with QVector:

    I didn't want to give a pointer to the whole vector

    You're aware that you did exactly this in your first post?

    int* p = &data[0];


  • Moderators

    @Loc888 said in Random crash with QVector:

    I wanted to split the data from the UI, so that's why they are not inside 1 class.

    It is good that you want to keep your code organized and split the data from the UI.

    Be warned though: When you try to pass an internal data pointer from Class B to Class A, you are breaking encapsulation which is bad (see https://stackoverflow.com/questions/16014290/simple-way-to-understand-encapsulation-and-abstraction )

    To maintain encapsulation, don't pass a pointer to a vector element. Don't pass the whole vector either. Instead, pass the index only, and design some class methods to let you access the data easily. For example:

    class Database {
    public:
        // TODO: Check that the index is valid before accessing m_data
        int getData(int index) { return m_data[index]; }
        void setData(int index, int newValue) { m_data[index] = newValue; }
    
    private:
        QVector<int> m_data;
    };
    

    Your GUI class should call the getData() and setData() functions instead of using a pointer to access the vector's data.

    Note: Qt's Model View classes are designed this way. A Model contains the data; a View is the UI.


Log in to reply