You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用GDAL/OGR正确读取Shapefile几何并避免内存泄漏

正确使用GDAL/OGR读取Shapefile几何数据并避免内存泄漏

你的代码存在两个核心内存泄漏问题,以下是问题分析和修正方案:

问题根源

  1. 未释放OGRFeature对象:每次调用GetNextFeature()获取的OGRFeature必须通过OGRFeature::DestroyFeature()销毁,否则feature本身及关联的资源(包括未被转移所有权的几何)会持续占用内存。
  2. 几何对象所有权混淆:
    • 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;
}

关键修正点说明

  1. OGRFeature的销毁:在循环中处理完每个feature后,必须调用OGRFeature::DestroyFeature(feature),这是解决内存泄漏的核心步骤。
  2. 几何对象的释放:
    • 若通过StealGeometry()获取几何,用OGRGeometryFactory::destroyGeometry()释放,因为GDAL的几何对象由工厂创建,需对应工厂方法销毁。
    • 若需要保留feature的原始几何(不转移所有权),需调用geometry->Clone()获取副本,副本的所有权归调用者,同样用OGRGeometryFactory::destroyGeometry()释放,同时仍需销毁原feature。
  3. 资源清理完整性:添加了数据集和图层的空指针判断,避免空指针访问,确保异常情况下资源也能正确释放。

内容的提问来源于stack exchange,提问作者JoeliP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 18:13:10