【问题标题】:ecCodes (grib reading library) does not free the memoryecCodes(grib 阅读库)不会释放内存
【发布时间】:2021-11-21 03:47:53
【问题描述】:

我在我的项目中使用ecCodes library,我遇到了在读取文件之间没有释放内存的问题。

代表问题的最小示例是这样的(基本上是这两个库 API 使用示例 [1](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.5GB。在打开新文件之前,使用codes_handle_delete() 和fclose() 关闭前一个文件。 因此,预期的行为是内存使用量保持在 1.5GB 左右。然而,实际上内存使用量稳步增加到大约 6.5GB,并在程序关闭时被释放(见下面的截图)。

此特定示例已在 CLion 上使用 CMake(发布配置)运行,但在所有其他配置以及我的其他使用 FFI 调用 ecCodes 的 Rust 项目中也会出现问题。

该库似乎经过了良好的测试和支持,因此它似乎不太可能是库错误。因此,这是预期的行为还是我的代码错误?如果是后者,我该如何纠正?

我正在使用安装了 apt 的 Ubuntu 21.04 和 ecCodes 2.20.0

【问题讨论】:

  • 我提供的链接可能无关紧要,但请看:stackoverflow.com/questions/47384177/…。由于您的 RAM 至少约为 16.7 GB,因此请尝试通过重复三次来调试它;如果失败,那么我不知道答案,如果不是,我给出的链接是相关的。
  • 您正在将一些数据推送到向量。读完每个文件后vector的大小是多少?
  • 顺便说一句,您没有检查文件是否已成功打开。您可以在fopen() 之后进行安全检查,如下所示:if (f == nullptr) return 1;
  • @kiner_shah 所有迭代后向量的大小为 6600 个元素 (50 KB),因此可以忽略不计。在我的实际代码中,我检查了文件是否成功打开。
  • @FaranAiki 感谢您的建议。我做了这个实验(并为它关闭了交换)并且内存使用量上升,直到所有的地狱都崩溃了。所以这实际上可能是库中的一个错误。

标签: c++ c grib grib-api eccodes


【解决方案1】:

于是我联系了图书馆作者,发现我没有仔细阅读this example。

为了让 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);
}   

之后,内存使用量的变化几乎不明显。

【讨论】:

    猜你喜欢
    • 2011-04-18
    • 2020-11-12
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    相关资源
    最近更新 更多