首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何防止内存泄漏?

如何防止内存泄漏?
EN

Stack Overflow用户
提问于 2022-03-16 14:22:30
回答 2查看 453关注 0票数 1

下面是关于使用C++解释器的内存管理问题的简化版本。

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

为了防止不断增长的内存泄漏,我需要对这些代码进行什么更改?

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

我在Windows10上使用Python3.10.2。C++正在由Visual编译成C++14标准。我已经安装了OpenAI-Gym版本0.22.0。

代码语言:javascript
运行
复制
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;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-03-16 18:44:13

问题既不是在Python中,也不是在它与C++的接口中。问题是在Box2D,这是使用的一些OpenAI健身房环境。

我可以重复上面的代码,同时创建一个不使用Box2D的不同环境(例如“Cartpol-v1”),让它在没有任何内存泄漏的情况下无休止地运行。一旦我将Box2D环境放回(如"BipedalWalker-v3“或"LunarLander-v2"),内存泄漏就会再次出现。

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

任何环境上的重置功能都是它进行大量准备运行的地方,也是内存泄漏发生的地方。如果Box2D环境被无休止地创建和销毁,则不会出现内存泄漏。创建,重置,然后销毁?内存泄漏。

谢谢大家的帮助,但这是底层库中的一个bug。我得去那里递交。

票数 0
EN

Stack Overflow用户

发布于 2022-03-16 15:10:12

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

一般来说,虽然您已经将其描述为简化的代码版本,但它仍然相当复杂。我要说的是,继续把它去掉,直到问题解决为止。这应该能告诉你问题出在哪里。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71498764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档