如何使用GDAL/OGR正确读取Shapefile几何并避免内存泄漏
正确使用GDAL/OGR读取Shapefile几何数据并避免内存泄漏
你的代码存在两个核心内存泄漏问题,以下是问题分析和修正方案:
问题根源
- 未释放OGRFeature对象:每次调用
GetNextFeature()获取的OGRFeature必须通过OGRFeature::DestroyFeature()销毁,否则feature本身及关联的资源(包括未被转移所有权的几何)会持续占用内存。 - 几何对象所有权混淆:
GetGeometryRef()返回的是feature所属几何的引用,所有权仍归feature,不能直接delete或用工厂销毁,必须通过销毁feature释放这部分内存。StealGeometry()会将几何所有权转移给调用者,但原feature仍需销毁,否则feature自身内存泄漏。
修正后的完整代码
#include <QCoreApplication> #include <QTextStream> #include <QDebug> #include <gdal/gdalwarper.h> #include <gdal/ogrsf_frmts.h> void freeshapes1(QList<OGRGeometry*>& vectors){ foreach (OGRGeometry* vector, vectors) { if (vector) { // 对应StealGeometry获取的几何,用工厂方法销毁 OGRGeometryFactory::destroyGeometry(vector); } } vectors.clear(); } QList<OGRGeometry*> loadshapes1(QString vecfile){ QList<OGRGeometry*> retval; unsigned int openFlags = GDAL_OF_VECTOR | GDAL_OF_READONLY; GDALDataset * srcDataset = static_cast<GDALDataset *>( GDALOpenEx( vecfile.toLocal8Bit().constData(), openFlags, NULL, NULL, NULL ) ); if (!srcDataset) { qWarning() << "Failed to open vector file"; return retval; } OGRLayer *layer = srcDataset->GetLayer(0); if (!layer) { qWarning() << "Failed to get layer from dataset"; GDALClose(srcDataset); return retval; } OGRFeature *feature; layer->ResetReading(); while ((feature = layer->GetNextFeature()) != nullptr) { // 通过StealGeometry转移几何所有权 OGRGeometry *geometry = feature->StealGeometry(); if(geometry != nullptr){ retval.append(geometry); } // 必须销毁feature,释放其自身内存 OGRFeature::DestroyFeature(feature); } GDALClose(srcDataset); return retval; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qWarning() << "Enter to start application"; QTextStream input(stdin); input.readLine(); GDALAllRegister(); for(int i = 0; i < 1000; i++){ if( i % 100 == 0){ qWarning() << i; } QList<OGRGeometry*> list = loadshapes1(MY_VECTOR_PATH); freeshapes1(list); } qWarning() << "Application done, check memory"; input.readLine(); return 0; }
关键修正点说明
- OGRFeature的销毁:在循环中处理完每个feature后,必须调用
OGRFeature::DestroyFeature(feature),这是解决内存泄漏的核心步骤。 - 几何对象的释放:
- 若通过
StealGeometry()获取几何,用OGRGeometryFactory::destroyGeometry()释放,因为GDAL的几何对象由工厂创建,需对应工厂方法销毁。 - 若需要保留feature的原始几何(不转移所有权),需调用
geometry->Clone()获取副本,副本的所有权归调用者,同样用OGRGeometryFactory::destroyGeometry()释放,同时仍需销毁原feature。
- 若通过
- 资源清理完整性:添加了数据集和图层的空指针判断,避免空指针访问,确保异常情况下资源也能正确释放。
内容的提问来源于stack exchange,提问作者JoeliP
相关产品推荐
相关产品推荐

