Bug report #777
crashes with python reference to destroyed objects (e.g exportToWkt() crashes when geom has been deleted)
|Affected QGIS version:||master||Regression?:||No|
|Operating System:||All||Easy fix?:||No|
|Pull Request or Patch supplied:||No||Resolution:|
|Crashes QGIS or corrupts data:||Yes||Copied to github as #:||10836|
When a feature is destroyed, if it has ownership over a geometry, it deletes that geometry. After that point, if one tries to call functions on the geometry, it will return nulls (Linux) or cause a KERN_PROTECTION_FAILURE (OS X).
This can be reproduced by selecting a feature, then typing the following into the Python console:
(Sometimes it requires calling it twice to reproduce the crash -- however, it will never return the correct answer.)
The reason for this appears to be that the feature created when it is pulled out of the list is then destoryed before exportToWkt() is called, taking the geometry with it.
A workaround is to instead call geometryAndOwnership(), which tells the feature to not destroy the geometry.
It seems like this problem may actually be exportGeosToWkb -- functions like wkbType() fail in the same way. It's possible that the mGeometry check at the beginning of these functions needs to move before teh exportGeosToWkb(), or that the exportGeosToWkb() needs to more resilient against being deleted.
Refine QgsFeature geometry getters/setters
All pointer based methods have been removed.
Now we have only:
void setGeometry( const QgsGeometry& geom )
QgsGeometry geometry() const
Benefits include avoiding a whole lot of tricky pointer lifetime
issues, potential memory leaks, and finally closing #777, which
has survived for over 9 years!...
Impacts on PyQGIS code:
- no more need for the messy
g = QgsGeometry( feature.geometry() )
workaround, just use g = feature.geometry() instead
- IMPORTANT: you can no longer test whether a feature has geometry
using `if f.geometry():`, since QgsFeature::geometry() will
always return an object. Instead, use
`if not f.geometry().isEmpty():`, or preferably the new method
`if not f.hasGeometry():`
#1 Updated by Martin Dobias about 12 years ago
The problem here is in python bindings because the scenario seems to be like this:
1. get feature
2. store geometry's reference in Python
3. feature is deleted (together with geometry)
4. reference in Python still exists, but the object it's pointing to doesn't
I'm trying to find out how to cope with this correctly...