Skip to content

Commit 4ddcb61

Browse files
Fix memory leak in reading data (#209)
1 parent cf7672c commit 4ddcb61

File tree

2 files changed

+90
-68
lines changed

2 files changed

+90
-68
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# CHANGELOG
22

3+
## 0.5.1
4+
5+
### Bug fixes
6+
7+
- Fix memory leak in reading files (#207)
8+
39
## 0.5.0 (2023-01-16)
410

511
### Major enhancements

pyogrio/_io.pyx

Lines changed: 84 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -642,42 +642,47 @@ cdef get_features(
642642
field_data_view = [field_data[field_index][:] for field_index in range(n_fields)]
643643
i = 0
644644
while True:
645-
if num_features > 0 and i == num_features:
646-
break
647-
648645
try:
649-
ogr_feature = exc_wrap_pointer(OGR_L_GetNextFeature(ogr_layer))
646+
if num_features > 0 and i == num_features:
647+
break
650648

651-
except NullPointerError:
652-
# No more rows available, so stop reading
653-
break
649+
try:
650+
ogr_feature = exc_wrap_pointer(OGR_L_GetNextFeature(ogr_layer))
654651

655-
except CPLE_BaseError as exc:
656-
if "failed to prepare SQL" in str(exc):
657-
raise ValueError(f"Invalid SQL query") from exc
652+
except NullPointerError:
653+
# No more rows available, so stop reading
654+
break
655+
656+
except CPLE_BaseError as exc:
657+
if "failed to prepare SQL" in str(exc):
658+
raise ValueError(f"Invalid SQL query") from exc
658659

659-
raise FeatureError(str(exc))
660+
raise FeatureError(str(exc))
660661

661-
if i >= num_features:
662-
raise FeatureError(
663-
"GDAL returned more records than expected based on the count of "
664-
"records that may meet your combination of filters against this "
665-
"dataset. Please open an issue on Github "
666-
"(https://github.com/geopandas/pyogrio/issues) to report encountering "
667-
"this error."
668-
) from None
662+
if i >= num_features:
663+
raise FeatureError(
664+
"GDAL returned more records than expected based on the count of "
665+
"records that may meet your combination of filters against this "
666+
"dataset. Please open an issue on Github "
667+
"(https://github.com/geopandas/pyogrio/issues) to report encountering "
668+
"this error."
669+
) from None
669670

670-
if return_fids:
671-
fid_view[i] = OGR_F_GetFID(ogr_feature)
671+
if return_fids:
672+
fid_view[i] = OGR_F_GetFID(ogr_feature)
672673

673-
if read_geometry:
674-
process_geometry(ogr_feature, i, geom_view, force_2d)
674+
if read_geometry:
675+
process_geometry(ogr_feature, i, geom_view, force_2d)
675676

676-
process_fields(
677-
ogr_feature, i, n_fields, field_data, field_data_view,
678-
field_indexes, field_ogr_types, encoding
679-
)
680-
i += 1
677+
process_fields(
678+
ogr_feature, i, n_fields, field_data, field_data_view,
679+
field_indexes, field_ogr_types, encoding
680+
)
681+
i += 1
682+
finally:
683+
if ogr_feature != NULL:
684+
OGR_F_Destroy(ogr_feature)
685+
ogr_feature = NULL
681686

682687
# There may be fewer rows available than expected from OGR_L_GetFeatureCount,
683688
# such as features with bounding boxes that intersect the bbox
@@ -733,24 +738,30 @@ cdef get_features_by_fid(
733738
field_data_view = [field_data[field_index][:] for field_index in range(n_fields)]
734739

735740
for i in range(count):
736-
fid = fids[i]
737-
738741
try:
739-
ogr_feature = exc_wrap_pointer(OGR_L_GetFeature(ogr_layer, fid))
742+
fid = fids[i]
740743

741-
except NullPointerError:
742-
raise FeatureError(f"Could not read feature with fid {fid}") from None
744+
try:
745+
ogr_feature = exc_wrap_pointer(OGR_L_GetFeature(ogr_layer, fid))
743746

744-
except CPLE_BaseError as exc:
745-
raise FeatureError(str(exc))
747+
except NullPointerError:
748+
raise FeatureError(f"Could not read feature with fid {fid}") from None
746749

747-
if read_geometry:
748-
process_geometry(ogr_feature, i, geom_view, force_2d)
750+
except CPLE_BaseError as exc:
751+
raise FeatureError(str(exc))
752+
753+
if read_geometry:
754+
process_geometry(ogr_feature, i, geom_view, force_2d)
755+
756+
process_fields(
757+
ogr_feature, i, n_fields, field_data, field_data_view,
758+
field_indexes, field_ogr_types, encoding
759+
)
760+
finally:
761+
if ogr_feature != NULL:
762+
OGR_F_Destroy(ogr_feature)
763+
ogr_feature = NULL
749764

750-
process_fields(
751-
ogr_feature, i, n_fields, field_data, field_data_view,
752-
field_indexes, field_ogr_types, encoding
753-
)
754765

755766
return (geometries, field_data)
756767

@@ -781,42 +792,47 @@ cdef get_bounds(
781792

782793
i = 0
783794
while True:
784-
if num_features > 0 and i == num_features:
785-
break
786-
787795
try:
788-
ogr_feature = exc_wrap_pointer(OGR_L_GetNextFeature(ogr_layer))
796+
if num_features > 0 and i == num_features:
797+
break
789798

790-
except NullPointerError:
791-
# No more rows available, so stop reading
792-
break
799+
try:
800+
ogr_feature = exc_wrap_pointer(OGR_L_GetNextFeature(ogr_layer))
793801

794-
except CPLE_BaseError as exc:
795-
if "failed to prepare SQL" in str(exc):
796-
raise ValueError(f"Invalid SQL query") from exc
797-
else:
798-
raise FeatureError(str(exc))
802+
except NullPointerError:
803+
# No more rows available, so stop reading
804+
break
799805

800-
if i >= num_features:
801-
raise FeatureError(
802-
"Reading more features than indicated by OGR_L_GetFeatureCount is not supported"
803-
) from None
806+
except CPLE_BaseError as exc:
807+
if "failed to prepare SQL" in str(exc):
808+
raise ValueError(f"Invalid SQL query") from exc
809+
else:
810+
raise FeatureError(str(exc))
804811

805-
fid_view[i] = OGR_F_GetFID(ogr_feature)
812+
if i >= num_features:
813+
raise FeatureError(
814+
"Reading more features than indicated by OGR_L_GetFeatureCount is not supported"
815+
) from None
806816

807-
ogr_geometry = OGR_F_GetGeometryRef(ogr_feature)
817+
fid_view[i] = OGR_F_GetFID(ogr_feature)
808818

809-
if ogr_geometry == NULL:
810-
bounds_view[:,i] = np.nan
819+
ogr_geometry = OGR_F_GetGeometryRef(ogr_feature)
811820

812-
else:
813-
OGR_G_GetEnvelope(ogr_geometry, &ogr_envelope)
814-
bounds_view[0, i] = ogr_envelope.MinX
815-
bounds_view[1, i] = ogr_envelope.MinY
816-
bounds_view[2, i] = ogr_envelope.MaxX
817-
bounds_view[3, i] = ogr_envelope.MaxY
821+
if ogr_geometry == NULL:
822+
bounds_view[:,i] = np.nan
818823

819-
i += 1
824+
else:
825+
OGR_G_GetEnvelope(ogr_geometry, &ogr_envelope)
826+
bounds_view[0, i] = ogr_envelope.MinX
827+
bounds_view[1, i] = ogr_envelope.MinY
828+
bounds_view[2, i] = ogr_envelope.MaxX
829+
bounds_view[3, i] = ogr_envelope.MaxY
830+
831+
i += 1
832+
finally:
833+
if ogr_feature != NULL:
834+
OGR_F_Destroy(ogr_feature)
835+
ogr_feature = NULL
820836

821837
# Less rows read than anticipated, so drop empty rows
822838
if i < num_features:

0 commit comments

Comments
 (0)