ecCodes (библиотека чтения grib) не освобождает память

Я использую в своем проекте , и я столкнулся с проблемой, библиотеку ecCodesзаключающейся в том, что память не освобождается между чтением файлов.

Минимальный пример, представляющий проблему, таков (и в основном представляет собой комбинацию этих двух примеров использования API библиотеки [ ](https://confluence.ecmwf.int/display/ECC/grib_get_keys) [2]:

      #include <string>
#include <vector>
#include <iostream>
#include "eccodes.h"

int main() {

    std::string filenames[] = {"../data/era5_model.grib", "../data/era5_model2.grib", "../data/era5_model3.grib",
                               "../data/era5_model4.grib"};

    std::vector<long> vec = {};

    for (auto & filename : filenames) {
        FILE* f = fopen(filename.c_str(), "r");
        int err = 0;
        codes_handle* h;

        while ((h = codes_handle_new_from_file(nullptr, f, PRODUCT_GRIB, &err)) != nullptr) {
            long k1 = 0;
            err = codes_get_long(h, "level", &k1);
            vec.push_back(k1);
        }

        codes_handle_delete(h);
        fclose(f);
    }

    std::cout << vec[52];

    return 0;
}

В этом примере программа считывает 4 идентичных файла ERA5, каждый размером 1,5 ГБ. Перед открытием нового файла предыдущий закрывается с помощью code_handle_delete () и fclose (). Таким образом, ожидается, что использование памяти останется на уровне около 1,5 ГБ. Однако на самом деле использование памяти постоянно увеличивается примерно до 6,5 ГБ и освобождается при закрытии программы (см. Снимок экрана ниже).

Этот конкретный пример был запущен на CLion с CMake (конфигурация выпуска), но проблема возникает с любой другой конфигурацией, а также в моем другом проекте Rust, который вызывает ecCodes с FFI.

Библиотека кажется хорошо протестированной и поддерживаемой, поэтому маловероятно, что это ошибка библиотеки. Следовательно, это ожидаемое поведение или мой код неправильный? Если второе, как я могу это исправить?

Я использую Ubuntu 21.04 и ecCodes 2.20.0, установленные с apt

1 ответ

Я связался с авторами библиотеки и понял, что недостаточно внимательно прочитал этот пример .

Чтобы ecCodes правильно освободили память codes_handleследует удалять каждый раз, когда он создается (аналогично тому, как вы должны освобождать память каждый раз, когда вы ее выделяете). Поэтому в моем примере codes_handle_delete() должен быть ВНУТРИ while петля:

      while ((h = codes_handle_new_from_file(nullptr, f, PRODUCT_GRIB, &err)) != nullptr) {
    long k1 = 0;
    err = codes_get_long(h, "level", &k1);
    vec.push_back(k1);
    codes_handle_delete(h);
}   

После этого изменения использование памяти практически незаметно.

Другие вопросы по тегам