Search code examples
c++qtqt3d

Data pointer is <QArrayData::shared_null+24> when accessing data of Qt3DRender::QBuffer


I have such statements:

Qt3DRender::QAttribute *attribute = // ...

const float *posBufferPtr =
                reinterpret_cast<const float *>(attribute->buffer()->data().constData());

Generally, the pointer posBufferPtr is:

Normal pointer value

However, sometimes pointer value becomes strange:

Strange pointer value

I wonder what is the meaning of <QArrayData::shared_null+24>? I'm asking this, since when the pointer value is strange, my application gets messed up.

UPDATE

I fixed the bug by making sure my buffer contains data:

Qt3DRender::QGeometryRenderer *mesh = // ...

Qt3DRender::QGeometry *meshGeometry = mesh->geometry();

for (Qt3DRender::QAttribute *attribute : meshGeometry->attributes()) {
    Qt3DRender::QBuffer *buf = attribute->buffer();
    if (buf) {
        // If buffer is empty, use data-generator to make data available
        if (buf->data().isEmpty())
            buf->setData(buf->dataGenerator()->operator()());
        buf->setSyncData(true);
        buf->setAccessType(Qt3DRender::QBuffer::AccessType::ReadWrite);
    }
}

Solution

  • Looking in the file $QTDIR/qtbase/src/corelib/tools/qarraydata.h, we see this:

    struct Q_CORE_EXPORT QArrayData
    {
       [...]
    
       static const QArrayData shared_null[2];
       static QArrayData *sharedNull() Q_DECL_NOTHROW { return const_cast<QArrayData*>(shared_null); }
    }
    

    ... so we see that QArrayData::shared_null is a static/singleton QArrayData object (actually it's an array of two of them). Presumably it is being used as a sentinel-object; i.e. when another data structure such as Qt3DRender::QBuffer doesn't have a valid QArrayData object to point to, it points to shared_null instead, as a way to indicate that fact. Using a singleton rather than nullptr is useful in some situations because it means that their code doesn't have to guard every dereference with a if (buffer() != NULL) to avoid crashing when no valid QArrayData object is available.

    As for the +24 part, that indicates that your pointer is 24 bytes past the memory location where the QArrayData::shared_null object starts at. From looking at the code in qarraydata.h, it appears that the constData() method calculates the pointer to return by adding a qptrdiff offset value to its this-pointer; so presumably that offset-value is set to 24 in this case. However, I think the precise pointer returned is probably not important, since the QArrayData::shared_null object is unlikely to contain any usable data in any case, i.e. the array that data() is returning is likely of length 0 and therefore the pointer shouldn't be dereferenced.

    My suggestion is that before you try to use your posBufferPtr pointer, you should call attribute->buffer()->data().size() and verify that it's large enough for what you want to do with it, as a sanity-check. i.e. if you are trying to use the buffer as an array of float, the guard your usage of the data with a test like if (attribute->buffer()->data().size() >= sizeof(float)*num_floats_I_expect_to_be_there) or similar.