传递给C的SWIG生成对象的内存管理

Memory management of SWIG generated objects passed to C

本文关键字:对象 内存 管理 SWIG      更新时间:2023-10-16

我正在尝试使用SWIG包装用C++编写的Python库。该库使用接受字节缓冲区作为参数的函数调用。在Python中,我使用SWIG中的%array_class创建这些字节缓冲区。为了测试这一点,我制作了一个概念验证程序,我注意到将这些缓冲区传递给C++会导致严重的内存泄漏。具体来说,运行下面的代码会稳步提高Python应用程序的内存使用率(如在任务管理器上观察到的),在程序停止的地方,内存使用率会提高到250MB左右。C的打印输出表明程序确实按预期运行,但只是占用了更多内存。del buff语句会运行,但不会释放内存。我尝试在每个循环中创建和删除缓冲区,但结果相同。在C++中运行delete x;会使我的程序完全崩溃。

我的Swig接口文件:

%module example
%include "carrays.i"
%array_class(uint8_t, buffer);
%{
    #include "PythonConnector.h"
%}
%include "PythonConnector.h"

C头文件:

class PythonConnector {
    public:
        void print_array(uint8_t *x);
};

最小C定义函数

void PythonConnector::print_array(uint8_t *x) 
{
   //int i;
   //for (i = 0; i < 100; i++) {
   //   printf("[%d] = %dn", i, x[i]);
   //}
   //delete x;     // <-- This crashed the program
   return;
}

测试人员Python脚本

import time
import example
sizeBytes = 10000
buff = example.buffer(sizeBytes) 
for j in range(1000):
    # Initialize data buffer
    for i in range(sizeBytes):
        buff[i] = i%256
    buff[0] = 0
    example.PythonConnector().print_array(buff.cast())
    print(j)
del buff
time.sleep(10)

我是不是错过了什么?我怀疑SWIG会为每次将缓冲区传递给未垃圾收集的C++时创建一些代理对象。

编辑:

  • SWIG 3.0.7版
  • CPython 3.5 x64版
  • Windows 10操作系统

谢谢你的帮助。

好的,感谢@Flexo,我找到了答案。

问题在于示例的实例化。在每个循环中创建PythonConnector()。只在循环外实例化一次似乎可以解决内存问题:

import time
import example
sizeBytes = 10000
buff = example.buffer(sizeBytes) 
conn = example.PythonConnector()
for j in range(1000):
    # Initialize data buffer
    for i in range(sizeBytes):
        buff[i] = i%256
    buff[0] = 0
    conn.print_array(buff.cast())
    print(j)
del buff
time.sleep(10)

为什么许多连接器没有在原始代码中得到垃圾收集,这仍然是一个问题。