Python:使用ctypes的垃圾收集器行为

nic*_*ell 16 python garbage-collection ctypes

所以让我们说IC/C++代码分配一些内存,并返回一个指向它的指针.

#include <stdlib.h>

#ifdef __cplusplus
  extern "C" {
#endif

void Allocate(void **p) {
 int N=2048;
 *p=malloc(N);
}

#ifdef __cplusplus
 }
#endif
Run Code Online (Sandbox Code Playgroud)

我明白,释放这块内存是我的责任.现在假设我将其编译成共享库并使用ctypes从Python调用它,但是没有显式释放该内存.

import ctypes
from ctypes import cdll, Structure, byref
external_lib = cdll.LoadLibrary('libtest.so.1.0')
ptr=ctypes.c_void_p(0)
external_lib.Allocate(ctypes.byref(ptr))
Run Code Online (Sandbox Code Playgroud)

如果我用valgrind运行这个脚本,如果我编译test.cpp没有'-O3'标志,我会得到2048字节的内存泄漏.但是如果我使用'-O3'标志编译它,那么我不会得到内存泄漏.

这不是一个真正的问题 - 我会小心翼翼地明确释放我分配的任何内存.但我很好奇这种行为来自哪里.

我在linux中用以下脚本测试了这个.

g++ -Wall -c -fPIC -fno-common test.cpp -o libtest1.o
g++ -shared -Wl,-soname,libtest1.so.1 -o libtest1.so.1.0  libtest1.o

g++ -O3 -Wall -c -fPIC -fno-common test.cpp -o libtest2.o
g++ -shared -Wl,-soname,libtest2.so.1 -o libtest2.so.1.0  libtest2.o

valgrind python test1.py &> report1
valgrind python test2.py &> report2
Run Code Online (Sandbox Code Playgroud)

具有以下输出

报告1:

==27875== LEAK SUMMARY:
==27875==    definitely lost: 2,048 bytes in 1 blocks
==27875==    indirectly lost: 0 bytes in 0 blocks
==27875==      possibly lost: 295,735 bytes in 1,194 blocks
==27875==    still reachable: 744,633 bytes in 5,025 blocks
==27875==         suppressed: 0 bytes in 0 blocks
Run Code Online (Sandbox Code Playgroud)

报告2:

==27878== LEAK SUMMARY:
==27878==    definitely lost: 0 bytes in 0 blocks
==27878==    indirectly lost: 0 bytes in 0 blocks
==27878==      possibly lost: 295,735 bytes in 1,194 blocks
==27878==    still reachable: 746,681 bytes in 5,026 blocks
==27878==         suppressed: 0 bytes in 0 blocks
Run Code Online (Sandbox Code Playgroud)

jac*_*arg -1

此行为来自 gcc -O3 优化。gcc 发现分配的内存未使用并省略此代码块。

你可以参考这个问题:malloc和gcc优化2