如何释放在 SWIG 的自定义构造函数中分配的内存?

How to release memory allocated in custom Constructor in SWIG?

我有 SWIG 中的内存管理问题。

我在 C++ 中有这个对象 (TestStruct.h):

struct Buffer {
    uint8_t* data;
    int length;
}

我希望能够使用 python 列表或字符串初始化此对象并从 python 中销毁它而不会发生内存泄漏。 我的痛饮文件是:

%module test

%newobject Buffer;
%nodefaultctor Buffer;
%nodefaultdtor Buffer;

%{
    #include "TestStruct.h"
%}

%include "TestStruct.h"

%extend Buffer {
    Buffer(PyObject* inputList)
    {
        int leng = (int)PySequence_Length(inputList);
        uint8_t* temp = new uint8_t[leng];
        cout << "Buffer Constructor called: " << leng << "  " << (unsigned int)temp << endl;
        for(int i=0; i<leng; i++){
            PyObject *o = PySequence_GetItem(inputList,i);
            if (PyNumber_Check(o)) {
                temp[i] = (uint8_t) PyLong_AsLong(o);
                //cout << "uint8_t to C++: " << (int)temp[i] << endl;
            } else {
                PyErr_SetString(PyExc_ValueError,"Sequence elements must be integers");      
                return NULL;
            }
        }    
        Buffer* buff = new Buffer();
        buff->dataBuf = temp;
        buff->length = leng;
        return buff;
    }

    ~Buffer() {
        cout << "Buffer Destructor called: " << $self->length << "  " << (unsigned int)$self->dataBuf << endl;
        delete[] $self->dataBuf;
        delete $self;
    }
}

运行 下面的简单测试使 Python 的内存使用量飙升至 30MB

import test
import sys
import time

times = 1000
printsteps = False
print("performing memory stress test")
for j in range(times):
    sizeBytes = 1024 * 1
    input_list = list(range(sizeBytes))
    buffer = test.Buffer(input_list)

    del buffer 
    time.sleep(0.001)

每次循环运行,构造函数和析构函数都被调用(我用打印输出验证),但它不会解决内存分配问题。

我需要 Buffer 将其作为参数传递给另一个 SWIG 包装的函数,并且我希望能够使用 python 列表创建 Buffer 的数据。我尝试使用大致相同的代码使用类型映射(in 和 freearg),但它失败了。所以我想出了使用自定义构造函数和析构函数,但它不会解决内存泄漏的问题。欢迎任何输入

您在将 Python 列表转换为 C++ uint8_t[leng] 时对 Python C-API 的使用不正确并导致内存泄漏。重点是函数 PySequence_GetItem() returns 对序列项的 新引用 。因为您未能对该项目调用 Py_DECREF(),所以当列表本身被删除时,Python 将不会释放该项目的内存。

要修复,您只需在 for 循环中添加 Py_DECREF(o);

顺便说一下,Python 循环中的 del buffer 行是多余的。