[QGIS-Developer] QgsGeometry's .get() and segfaults

Julien Cabieces julien.cabieces at oslandia.com
Mon Mar 4 06:54:04 PST 2024


Hi,

Calling get() means that you get a reference of the QgsAbstractGeometry used by the
QgsGeometry object, but the QgsGeometry object (g) is still the
ownership of the QgsAbstractGeometry object (g_geom).

So, if you delete your QgsGeometry (g) you delete the owned
QgsAbstractGeometry (g_geom). And you would get quite the same issue if you
wanted to delete g_geom.

Best is to use constGet() and clone() your returned QgsAbstractGeometry
if you want to manipulate it independantly from its original QgsGeometry
owner.

Regarding detach(), it's because of a design pattern called "Implicit
Data Sharing" or "copy on write". When we copy a QgsGeometry, both objects are, under the hood,
referencing the same memory object (QgsGeometryPrivate d). When you end up modifying one of the object (moveVertex for
instance), you detach the modified object so the two are no longer
sharing the memory private object (hence the name "copy on write").

That's what happen when we call get(), we need to detach so other
QgsGeometry object would not be impacted by later modification of the
non-const returned object.


Hope that makes sense :)

Julien




> Hi list!
>
> I am using some time to learn more about the relationships between
> Python, C++, SIP, the QGIS API and everything in-between.
>
> And currently I am confused why this Python snippet leads to a segfault:
>
> from qgis.core import QgsGeometry
> g = QgsGeometry.fromWkt("POINT (1 2)")
> g_geom = g.get()
> del g
> print(g_geom.asWkt())
>
> I understand that deleting wrapped objects can lead to unexpected
> deletions of related objects (e. g. if I delete a PyQt parent object
> and then try to use an existing reference/"variablename" to a child of
> it) but at least from the documentation this does not seem related to
> that.
>
> https://github.com/qgis/QGIS/blob/dc73608a60229c9960ee65e308cfaba5f32566ec/src/core/geometry/qgsgeometry.h#L196
> says about QgsGeometry.get():
>> Returns a modifiable (non-const) reference to the underlying
>   abstract geometry primitive. This method can be slow to call, as it
>   may trigger a detachment of the geometry and a deep copy. Where
>   possible, use constGet() instead.
>
> I do not understand anything in the detach() function itself
> https://github.com/qgis/QGIS/blob/dc73608a60229c9960ee65e308cfaba5f32566ec/src/core/geometry/qgsgeometry.cpp#L102
> :o)
>
> Would my small snippet lead to a reference to the C++ object's
> geometry? Then I'd understand the segfault (although not why it would
> not trigger one of the usual "wrapped C/C++ object of type [...] has
> been deleted" errors) if I try to access it after the whole
> QgsGeometry might have been destroyed.
> Or does it get a "detached deep copy"? In that case it sounds like an
> independent object to me but I might be completely wrong.
>
> Are there any C++ or SIP terms you could throw my way for further reading?
>
> Thanks for your help!
>
> Cheers, Hannes
>
> _______________________________________________
> QGIS-Developer mailing list
> QGIS-Developer at lists.osgeo.org
> List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer
> Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer


-- 

Julien Cabieces
Senior Developer at Oslandia
julien.cabieces at oslandia.com


More information about the QGIS-Developer mailing list