传递给 C 的 SWIG 生成对象的内存管理
Memory management of SWIG generated objects passed to C
我正在尝试使用 SWIG 为 Python 包装一个用 C++ 编写的库。该库使用接受字节缓冲区作为参数的函数调用。在 Python 中,我使用来自 SWIG 的 %array_class 创建了这些字节缓冲区。我制作了一个概念验证程序来对此进行测试,我注意到与将这些缓冲区传递给 C++ 相关的显着内存泄漏。具体来说,运行宁下面的代码 稳步提高 Python 应用程序 的内存使用量(如在任务管理器上观察到的那样)高达约 250MB,程序停止. C 的打印输出表明程序 按预期执行 运行,但只是占用了更多内存。 del buff
语句运行s,但不释放内存。我尝试在每个循环中创建和删除缓冲区,但结果相同。
运行 delete x;
在 C++ 中使我的程序完全崩溃。
我的 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] = %d\n", 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 OS
感谢您的帮助。
好的,感谢@Flexo,我找到了答案。
问题是在每个循环中创建的 example.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)
问题仍然存在,为什么许多连接器没有在原始代码中进行垃圾收集。
我正在尝试使用 SWIG 为 Python 包装一个用 C++ 编写的库。该库使用接受字节缓冲区作为参数的函数调用。在 Python 中,我使用来自 SWIG 的 %array_class 创建了这些字节缓冲区。我制作了一个概念验证程序来对此进行测试,我注意到与将这些缓冲区传递给 C++ 相关的显着内存泄漏。具体来说,运行宁下面的代码 稳步提高 Python 应用程序 的内存使用量(如在任务管理器上观察到的那样)高达约 250MB,程序停止. C 的打印输出表明程序 按预期执行 运行,但只是占用了更多内存。 del buff
语句运行s,但不释放内存。我尝试在每个循环中创建和删除缓冲区,但结果相同。
运行 delete x;
在 C++ 中使我的程序完全崩溃。
我的 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] = %d\n", 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 OS
感谢您的帮助。
好的,感谢@Flexo,我找到了答案。
问题是在每个循环中创建的 example.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)
问题仍然存在,为什么许多连接器没有在原始代码中进行垃圾收集。