使用嵌入式 Python 检查 C++ 中的内存泄漏

问题描述

我正在编写嵌入 Python 模块的 C++ 代码。我在开始时只导入了一次模块;然后,C++ 代码从中重复调用单个函数。为此,我使用了以下语法(这里报告了一个最小的工作示例,假设 Python 函数采用两个浮点参数并返回一个浮点值):

int main() {
   
    // Initialise the Python interpreter
    Py_Initialize();

    PyObject *pFunc = NULL,*pModule = NULL;

    const char* module_name   = "mod_name";
    const char* function_name = "fun_name";

    // Importing module
    pModule = PyImport_ImportModule(module_name);

    // Sanity check on module pointer
    if (pModule == NULL) {
        PyErr_Print();
        std::cout << "ERROR importing module" << std::endl;
        std::exit(1);
    }

    // Import function from Python module 
    pFunc = PyObject_GetAttrString(pModule,function_name);
    if (pFunc == NULL) {
        Py_CLEAR(pModule);
        PyErr_Print();
        std::cout << "ERROR getting test function" << std::endl;
        std::exit(1);
    }

    // Free module pointer
    Py_CLEAR(pModule);


    double val1 = 1.5;
    double val2 = 2.5;

    for (int i = 0; i < 10; i++){
        
        // Specify inputs of the Python function that has to be called
        pArgs = PyTuple_Pack(2,PyFloat_FromDouble(val1),PyFloat_FromDouble(val2) );
 
         
        // Checking that the tuple packing was performed correctly
        if (pArgs == NULL) {
            PyErr_Print();
            std::cout << "ERROR packing arguments" << std::endl;
            std::exit(1);
        } 
        
   
        // Call the Python function and store the returned value in pValue
        pValue = PyObject_CallObject(pFunc,pArgs);

        // Checking that the function call was performed correctly
        if (pValue == NULL) {
            Py_CLEAR(pArgs);
            PyErr_Print();
            std::cout << "ERROR getting value from function" << std::endl;
            std::exit(1);
         }
    
        //SUCCESSFULLY COMPLETED PYTHON CALL
        double res= PyFloat_AsDouble(pValue);
    
        // Free all the allocated memory
        Py_CLEAR(pArgs);
        Py_CLEAR(pValue);
   
    } 

    // Free the shared pointer to python function
    Py_CLEAR(pFunc);
    Py_Finalize();
    return 0;
}

我已经使用 valgrind 分析了我的 C++ 可执行文件,以检查内存泄漏。虽然当我隔离代码的 C++ 部分时一切正常,但只要我运行带有嵌入式 Python 部分的完整代码,就会出现内存泄漏。请参阅以下原始代码的损失报告示例:valgrind loss report

我知道 valgrind 在与 Python 代码交互时可能会给出奇怪的结果,所以我在这里联系以查看在将 Python 嵌入到 C++ 中时是否有检查内存泄漏的最佳实践。

另外,这是我在这里的第一个问题,所以如果缺少任何有用的信息,请不要犹豫,提出要求!提前致谢

解决方法

您遇到的问题是 valgrind 了解通过 malloc 完成的分配,但它不了解来自 python 领域的分配。因此,如果 malloc 的分配仅从 python 分配中引用,则 valgrind 不会注意到这一点,并且会认为 malloc 的分配已泄露。

我的建议是您使用 https://github.com/vmware/chap,因为它可以识别两种类型的分配。

在没有 valgrind 的情况下运行您的程序,但在您的程序完成之前的某个时刻收集实时核心,使用 gcore 或通过在断点处从 gdb 运行“生成”。

然后启动 chap 并在 chap 提示下尝试以下操作:

count leaked

如果显示非零值,请查看 https://github.com/vmware/chap/blob/master/USERGUIDE.md 以获取有关如何分析泄漏的进一步建议。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...