[GRASS-SVN] r66236 - grass/trunk/lib/python/pygrass/vector
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Sep 15 13:10:09 PDT 2015
Author: huhabla
Date: 2015-09-15 13:10:09 -0700 (Tue, 15 Sep 2015)
New Revision: 66236
Modified:
grass/trunk/lib/python/pygrass/vector/geometry.py
Log:
pygrass vector: Implemented memory management for geometries to avoid memory leaks from line_cats and line_points structures
Modified: grass/trunk/lib/python/pygrass/vector/geometry.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/geometry.py 2015-09-15 15:38:42 UTC (rev 66235)
+++ grass/trunk/lib/python/pygrass/vector/geometry.py 2015-09-15 20:10:09 UTC (rev 66236)
@@ -259,34 +259,84 @@
gtype = None
def __init__(self, v_id=0, c_mapinfo=None, c_points=None, c_cats=None,
- table=None, writeable=False, is2D=True):
+ table=None, writeable=False, is2D=True, free_points=False,
+ free_cats=False):
+ """Constructor of a geometry object
+
+ :param v_id: The vector feature id
+ :param c_mapinfo: A pointer to the vector mapinfo structure
+ :param c_points: A pointer to a libvect.line_pnts structure, this
+ is optional, if not set an internal structure will
+ be allocated and free'd at object destruction
+ :param c_cats: A pointer to a libvect.line_cats structure, this
+ is optional, if not set an internal structure will
+ be allocated and free'd at object destruction
+ :param table: The attribute table to select attributes for
+ this feature
+ :param writeable: Not sure what this is for?
+ :param is2D: If True this feature has two dimensions, False if
+ this feature has three dimensions
+ :param free_points: Set this True if the provided c_points structure
+ should be free'd at object destruction, be aware
+ that no other object should free them, otherwise
+ you can expect a double free corruption segfault
+ :param free_cats: Set this True if the provided c_cats structure
+ should be free'd at object destruction, be aware
+ that no other object should free them, otherwise
+ you can expect a double free corruption segfault
+
+ """
self.id = v_id # vector id
self.c_mapinfo = c_mapinfo
self.is2D = (is2D if is2D is not None else
bool(libvect.Vect_is_3d(self.c_mapinfo) != 1))
+ # Set True if cats and points are allocated by this object
+ # to free the cats and points structures on destruction
+ self._free_points = False
+ self._free_cats = False
+
read = False
# set c_points
if c_points is None:
self.c_points = ctypes.pointer(libvect.line_pnts())
+ self._free_points = True
read = True
else:
self.c_points = c_points
+ self._free_points = free_points
# set c_cats
if c_cats is None:
self.c_cats = ctypes.pointer(libvect.line_cats())
+ self._free_cats = free_cats
read = True
else:
self.c_cats = c_cats
+ self._free_cats = True
if self.id and self.c_mapinfo is not None and read:
self.read()
# set the attributes as last thing to do
- self.attrs = None
+ self.attrs = None
if table is not None and self.cat is not None:
self.attrs = Attrs(self.cat, table, writeable)
+
+ def __del__(self):
+ """Take care of the allocated line_pnts and line_cats allocation
+ """
+ if self._free_points == True and self.c_points:
+ if self.c_points.contents.alloc_points > 0:
+ #print("G_free(points) [%i]"%(self.c_points.contents.alloc_points))
+ libgis.G_free(self.c_points.contents.x)
+ libgis.G_free(self.c_points.contents.y)
+ if self.c_points.contents.z:
+ libgis.G_free(self.c_points.contents.z)
+ if self._free_cats == True and self.c_cats:
+ if self.c_cats.contents.alloc_cats > 0:
+ #print("G_free(cats) [%i]"%(self.c_cats.contents.alloc_cats))
+ libgis.G_free(self.c_cats.contents.cat)
@property
def cat(self):
@@ -314,11 +364,6 @@
>>> pnt = Point(10, 100)
>>> pnt.to_wkt()
'POINT (10.0000000000000000 100.0000000000000000)'
-
- .. warning::
-
- Only ``POINT`` (2/3D) are supported, ``POINTM`` and ``POINT`` with:
- ``XYZM`` are not supported yet.
"""
return libvect.Vect_line_to_wkt(self.c_points, self.gtype, not self.is2D)
@@ -330,12 +375,6 @@
>>> wkb = pnt.to_wkb()
>>> len(wkb)
21
-
-
- .. warning::
-
- Only ``POINT`` (2/3D) are supported, ``POINTM`` and ``POINT`` with:
- ``XYZM`` are not supported yet.
"""
size = ctypes.c_size_t()
barray = libvect.Vect_line_to_wkb(self.c_points, self.gtype,
@@ -366,6 +405,19 @@
>>> print(pnt)
POINT Z (0.0000000000000000 0.0000000000000000 0.0000000000000000)
+
+ >>> c_points = ctypes.pointer(libvect.line_pnts())
+ >>> c_cats = ctypes.pointer(libvect.line_cats())
+ >>> p = Point(c_points = c_points, c_cats=c_cats)
+ >>> del p
+
+
+ >>> c_points = ctypes.pointer(libvect.line_pnts())
+ >>> c_cats = ctypes.pointer(libvect.line_cats())
+ >>> p = Point(c_points=c_points, c_cats=c_cats, free_points=True,
+ ... free_cats=True)
+ >>> del p
+
..
"""
# geometry type
@@ -1742,13 +1794,24 @@
def read_next_line(c_mapinfo, table=None, writeable=False,
c_points=None, c_cats=None, is2D=True):
"""Return the next geometry feature of a vector map."""
+
+ # Take care of good memory management
+ free_points = False
+ if c_points == None:
+ free_points = True
+
+ free_cats = False
+ if c_cats == None:
+ free_cats = True
+
c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
c_cats = c_cats if c_cats else ctypes.pointer(libvect.line_cats())
ftype, v_id, c_points, c_cats = c_read_next_line(c_mapinfo, c_points,
c_cats)
return GV_TYPE[ftype]['obj'](v_id=v_id, c_mapinfo=c_mapinfo,
c_points=c_points, c_cats=c_cats,
- table=table, writeable=writeable, is2D=is2D)
+ table=table, writeable=writeable, is2D=is2D,
+ free_points=free_points, free_cats=free_cats)
def c_read_line(feature_id, c_mapinfo, c_points, c_cats):
@@ -1768,6 +1831,15 @@
c_points=None, c_cats=None, is2D=True):
"""Return a geometry object given the feature id and the c_mapinfo.
"""
+ # Take care of good memory management
+ free_points = False
+ if c_points == None:
+ free_points = True
+
+ free_cats = False
+ if c_cats == None:
+ free_cats = True
+
c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
c_cats = c_cats if c_cats else ctypes.pointer(libvect.line_cats())
feature_id, ftype, c_points, c_cats = c_read_line(feature_id, c_mapinfo,
@@ -1775,9 +1847,10 @@
if GV_TYPE[ftype]['obj'] is not None:
return GV_TYPE[ftype]['obj'](v_id=feature_id, c_mapinfo=c_mapinfo,
c_points=c_points, c_cats=c_cats,
- table=table, writeable=writeable, is2D=is2D)
+ table=table, writeable=writeable, is2D=is2D,
+ free_points=free_points,
+ free_cats=free_cats)
-
if __name__ == "__main__":
import doctest
from grass.pygrass import utils
More information about the grass-commit
mailing list