我怎样才能防止这种内存泄漏?

How can I prevent this memory leak?

下面是我遇到的与使用 C++ 中的 Python 解释器相关的内存管理问题的简化版本。

下面的代码将 运行 正确,但它的内存占用会随着时间的推移逐渐增加。我添加了一行来手动调用 Python 垃圾收集;这并没有解决问题。

我需要用这段代码更改什么以防止不断增长的内存泄漏?

[编辑]:根据下面的建议,我进一步削减了 pythonTest 函数。它所做的只是创建一个环境,重置它,然后关闭它。内存泄漏仍然存在。

我在 Windows 10 上使用 Python 3.10.2。C++ 正在由 Visual Studio 编译为 C++14 标准。我安装了 OpenAI-Gym 版本 0.22.0。

void pythonTest(PyObject* inModule)
{
    // Section 1: Get the make function:
    PyObject* pMakeFunc = PyObject_GetAttrString(inModule, "make");

    PyObject* pMakeArgs = PyTuple_New(1);
    PyTuple_SetItem(pMakeArgs, 0, PyUnicode_FromString("LunarLanderContinuous-v2"));

    // Section 2: Get the environment and its functions:
    PyObject* pEnv = PyObject_CallObject(pMakeFunc, pMakeArgs);
    PyObject* pEnvReset = PyObject_GetAttrString(pEnv, "reset");
    PyObject* pEnvStep = PyObject_GetAttrString(pEnv, "step");
    PyObject* pEnvClose = PyObject_GetAttrString(pEnv, "close");
    PyObject* pEnvRender = PyObject_GetAttrString(pEnv, "render");

    // Section 3: Reset the environment to get the initial observation:
    PyObject* pInitialObsArray = PyObject_CallNoArgs(pEnvReset);
    PyObject* pInitialObsListFunc = PyObject_GetAttrString(pInitialObsArray, "tolist");
    PyObject* pInitialObsList = PyObject_CallNoArgs(pInitialObsListFunc);

    // Clear section 3:
    Py_CLEAR(pInitialObsList);
    Py_CLEAR(pInitialObsListFunc);
    Py_CLEAR(pInitialObsArray);

    // Clear section 2: Close the environment, first:
    PyObject_CallNoArgs(pEnvClose);
    Py_CLEAR(pEnvRender);
    Py_CLEAR(pEnvClose);
    Py_CLEAR(pEnvStep);
    Py_CLEAR(pEnvReset);

    Py_CLEAR(pEnv);

    // Clear section 1:
    Py_CLEAR(pMakeArgs);
    Py_CLEAR(pMakeFunc);
}

int main()
{
    Py_Initialize();

    // Get gym module:
    PyObject* pGymName = PyUnicode_FromString("gym");
    PyObject* pModule = PyImport_Import(pGymName);

    // Get garbage collection module and collect function:
    PyObject* pgcName = PyUnicode_FromString("gc");
    PyObject* pgcModule = PyImport_Import(pgcName);
    PyObject* pgcFunction = PyObject_GetAttrString(pgcModule, "collect");

    for (int k = 0; k < 1000000; ++k)
    {        
        pythonTest(pModule);
        
        // Manually invoke the garbage collection:
        PyObject* pGCReturn = PyObject_CallNoArgs(pgcFunction);
        auto objectsCollected = PyLong_AsLong(pGCReturn);
        std::cout << "Iteration " << k << " objects collected: " 
            << objectsCollected << std::endl;

        Py_CLEAR(pGCReturn);
    }

    Py_CLEAR(pgcFunction);
    Py_CLEAR(pgcModule);
    Py_CLEAR(pgcName);

    Py_CLEAR(pModule);
    Py_CLEAR(pGymName);

    Py_Finalize();

    return 0;
}

您每次循环都在创建一个新的 pActionList,但您似乎没有处理它。

一般来说,虽然您将此描述为代码的精简版本,但它仍然相当复杂。我会说继续剥离它直到问题消失。那应该告诉你问题出在哪里。

问题既不在 Python 也不在它的 C++ 接口中。问题出在一些 OpenAI Gym 环境使用的 Box2D 中。

我可以重复上面的代码,同时创建一个不使用 Box2D 的不同环境(例如“CartPole-v1”)并让它 运行 无休止地没有任何内存泄漏。一旦我放回 Box2D 环境(例如“BipedalWalker-v3”或“LunarLander-v2”),内存泄漏又回来了。

我可以在 Python 中完全重复上述过程并得到相同的结果。即使在每次环境破坏后手动 运行ning 垃圾收集,应用程序分配的内存也会无限增长。

任何环境中的重置函数都是为 运行 做大量准备的地方,也是发生内存泄漏的地方。如果无休止地创建和销毁 Box2D 环境,则不会发生内存泄漏。创建,重置,然后销毁?内存泄漏。

谢谢大家的帮助,但这是底层库中的一个错误。我需要去那里提交。