Search code examples
c++memory-leaksgdalogr

GDAL OGR C++ Geometry Memory Leak


How to correctly read geometries from a shapefile using gdal and ogr and freeing the geometries without memory leaks?

Here is a minimal example that continously reads and tries to free the geometries, but memory is never released and is consumed more and more. Example is made with Qt.

#include <QCoreApplication>
#include <QTextStream>
#include <QDebug>

#include <gdal/gdalwarper.h>
#include <gdal/ogrsf_frmts.h>

void freeshapes1(QList<OGRGeometry*> vectors){

    foreach (OGRGeometry* vector, vectors) {
        delete vector;//Leaks
        //OGRGeometryFactory::destroyGeometry(vector);//Leaks
    }
}
QList<OGRGeometry*> loadshapes1(QString vecfile){

    QList<OGRGeometry*> retval;

    unsigned int openFlags = GDAL_OF_VECTOR | GDAL_OF_READONLY;
    GDALDataset * srcDataset = static_cast<GDALDataset *>( GDALOpenEx(
    (const char*)vecfile.toLocal8Bit().data(),
    openFlags,
    NULL, NULL, NULL ) );

    OGRLayer *layer = srcDataset->GetLayer(0);

    OGRFeature *feature;
    layer->ResetReading();
    while ((feature = layer->GetNextFeature()) != nullptr) {

        OGRGeometry *geometry = feature->GetGeometryRef();//Leaks
        //OGRGeometry *geometry = feature->StealGeometry();//Leaks

        if(geometry == nullptr){
            continue;
        }
        retval.append(geometry);
    }

    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;
    }

Solution

  • From the GDAL documentation: https://gdal.org/doxygen/classOGRLayer.html#a47d21ff33b32d14fa4e9885b9edecad6

    OGRFeature * OGRLayer::GetNextFeature   (       )   
    pure virtual
    

    Fetch the next available feature from this layer. The returned feature becomes the responsibility of the caller to delete with OGRFeature::DestroyFeature(). It is critical that all features associated with an OGRLayer (more specifically an OGRFeatureDefn) be deleted before that layer/datasource is deleted.

    OGRFeature::GetGeometryRef returns a pointer to an internal field in the feature object. You should free the feature object.