Python CFFI内存管理问题
Python CFFI memory management issues
我正在 Ubuntu 编程,Python 2.7.3
。
我正在使用 CFFI 填充 Python 列表,其中的值来自某些 C 代码。
该列表非常大:打印时大约有 71 000 个字符。
C 代码使用了很多库。因此,下面的代码只是为了更好地理解正在发生的事情。
datas_list = []
for i in range( 0, x ):
c_pDataStructure = ffi.new( "c_DataStructure[]", 1 ) // Create a pointer to the data structure
c.SomeCFunction( c_pDataStructure ) // Populate the data structure
datas_list.append( c.GetSomeInfo( c_pDataStructure ) ) // Get some info from the data structure
c.FreeDataStructure( c_pDataStructure ) // Release dynamically allocated memory
程序 运行 使用 Wingware IDE 很好,但从命令行启动时以 glibc 错误 (*** glibc detected *** python: free(): invalid next size (fast): 0x0000000003b0b080 ***
) 结束,就在之前:
c_pDataStructure = ffi.new( "c_Datastructure[]", 1)
阅读 wim 的 后,我检查了 IDE 和命令行是否 运行 使用相同的解释器编译代码 — 它们是 (/usr/bin/python
).
编辑(valgrind 报告):
==5089== Process terminating with default action of signal 11 (SIGSEGV)
==5089== General Protection Fault
==5089== at 0x54FBB0: PyObject_Malloc (in /usr/bin/python2.7)
==5089== by 0x10B30625: allocate_owning_object (_cffi_backend.c:2972)
==5089== by 0x10B40EE8: allocate_with_allocator.constprop.84 (_cffi_backend.c:3032)
==5089== by 0x10B41010: direct_newp (_cffi_backend.c:3153)
==5089== by 0x10B4138C: b_newp (_cffi_backend.c:3177)
==5089== by 0x4F95A4: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x5008C1: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==5089== by 0x4F9AB7: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
编辑:
这里有一些关于 C 数据结构的更多信息。这是它的样子:
typedef struct _STRUCT3{
some int, char*
}STRUCT3, *PSTRUCT3;
typedef struct _STRUCT2{
some int
PSTRUCT3 pStruct3;
}STRUCT3, *PSTRUCT3;
typedef struct _STRUCT1{
some int, char*
PSTRUCT2 pStruct2;
}STRUCT1, *PSTRUCT1;
我编写了一个小 C 程序来分配/释放完整的 C 结构,valgrind
没有发现任何内存泄漏。
问题:
- 以上
valgrind
报告的确切含义是什么?
- 运行ning 程序与
IDE 和从命令行?
注意:IDE 将 Python 参数 -u (unbuffered)
用于 运行 程序,但将其添加到命令行没有任何区别。
- 当我自己解除分配结构时,Python 的垃圾收集器是否起作用?我应该改用
ffi.gc( c_pDataStructure, c.FreeDataStructure )
吗?
我找到了解决问题的方法:
我用 ffi.gc(cdata, destructor)
创建了结构。我的 Python 代码现在看起来像:
data_list = []
for i in range( 0, x ):
# Create a pointer to the data structure and tell the garbage collector how to destroy it
gc_c_pDataStructure = ffi.gc( c.CreateDataStructure(), c.FreeDataStructure )
c.SomeCFunction( gc_c_pDataStructure ) # Populate the data structure
datas_list.append( c.GetSomeInfo( gc_c_pDataStructure ) ) # Store some data
这里有一些与 ffi.gc()
相关的链接:
- Python CFFI documentation
- David's thread
这是创建数据结构的 C 函数(根据问题中的结构示例):
PSTRUCT1 CreateDataStructure()
{
PSTRUCT1 pStruct1 = ( PSTRUCT1 ) malloc( sizeof( STRUCT1 ) );
_SetDummyValues( pStruct1 );
return pStruct1;
}
如您所见,我必须创建函数 void _SetDummyValues( PSTRUCT1 pStruct1 )
。该函数将给定的结构指针设置为 NULL。
这可能也与 Coverity 在某些
我们的 CFFI 生成的代码:
x0 = (void *)alloca((size_t)datasize);
...
{
free(x0);
}
如您所见,它在堆栈分配的内存上调用 free。
我正在 Ubuntu 编程,Python 2.7.3
。
我正在使用 CFFI 填充 Python 列表,其中的值来自某些 C 代码。
该列表非常大:打印时大约有 71 000 个字符。
C 代码使用了很多库。因此,下面的代码只是为了更好地理解正在发生的事情。
datas_list = []
for i in range( 0, x ):
c_pDataStructure = ffi.new( "c_DataStructure[]", 1 ) // Create a pointer to the data structure
c.SomeCFunction( c_pDataStructure ) // Populate the data structure
datas_list.append( c.GetSomeInfo( c_pDataStructure ) ) // Get some info from the data structure
c.FreeDataStructure( c_pDataStructure ) // Release dynamically allocated memory
程序 运行 使用 Wingware IDE 很好,但从命令行启动时以 glibc 错误 (*** glibc detected *** python: free(): invalid next size (fast): 0x0000000003b0b080 ***
) 结束,就在之前:
c_pDataStructure = ffi.new( "c_Datastructure[]", 1)
阅读 wim 的 /usr/bin/python
).
编辑(valgrind 报告):
==5089== Process terminating with default action of signal 11 (SIGSEGV)
==5089== General Protection Fault
==5089== at 0x54FBB0: PyObject_Malloc (in /usr/bin/python2.7)
==5089== by 0x10B30625: allocate_owning_object (_cffi_backend.c:2972)
==5089== by 0x10B40EE8: allocate_with_allocator.constprop.84 (_cffi_backend.c:3032)
==5089== by 0x10B41010: direct_newp (_cffi_backend.c:3153)
==5089== by 0x10B4138C: b_newp (_cffi_backend.c:3177)
==5089== by 0x4F95A4: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x5008C1: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==5089== by 0x4F9AB7: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
编辑:
这里有一些关于 C 数据结构的更多信息。这是它的样子:
typedef struct _STRUCT3{
some int, char*
}STRUCT3, *PSTRUCT3;
typedef struct _STRUCT2{
some int
PSTRUCT3 pStruct3;
}STRUCT3, *PSTRUCT3;
typedef struct _STRUCT1{
some int, char*
PSTRUCT2 pStruct2;
}STRUCT1, *PSTRUCT1;
我编写了一个小 C 程序来分配/释放完整的 C 结构,valgrind
没有发现任何内存泄漏。
问题:
- 以上
valgrind
报告的确切含义是什么? - 运行ning 程序与
IDE 和从命令行?
注意:IDE 将 Python 参数-u (unbuffered)
用于 运行 程序,但将其添加到命令行没有任何区别。 - 当我自己解除分配结构时,Python 的垃圾收集器是否起作用?我应该改用
ffi.gc( c_pDataStructure, c.FreeDataStructure )
吗?
我找到了解决问题的方法:
我用 ffi.gc(cdata, destructor)
创建了结构。我的 Python 代码现在看起来像:
data_list = []
for i in range( 0, x ):
# Create a pointer to the data structure and tell the garbage collector how to destroy it
gc_c_pDataStructure = ffi.gc( c.CreateDataStructure(), c.FreeDataStructure )
c.SomeCFunction( gc_c_pDataStructure ) # Populate the data structure
datas_list.append( c.GetSomeInfo( gc_c_pDataStructure ) ) # Store some data
这里有一些与 ffi.gc()
相关的链接:
- Python CFFI documentation
- David's thread
这是创建数据结构的 C 函数(根据问题中的结构示例):
PSTRUCT1 CreateDataStructure()
{
PSTRUCT1 pStruct1 = ( PSTRUCT1 ) malloc( sizeof( STRUCT1 ) );
_SetDummyValues( pStruct1 );
return pStruct1;
}
如您所见,我必须创建函数 void _SetDummyValues( PSTRUCT1 pStruct1 )
。该函数将给定的结构指针设置为 NULL。
这可能也与 Coverity 在某些 我们的 CFFI 生成的代码:
x0 = (void *)alloca((size_t)datasize);
...
{
free(x0);
}
如您所见,它在堆栈分配的内存上调用 free。