我正在使用一些使用ctypes的库。该库有其自己的方法来处理堆内存,因此在C中,我将执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intcall.h"
int main(void) {
long status = -1;
char host[10] = "xx.x.x.xx";
char user[7] = "xxxxxx";
char pass[7] = "xxxxxx";
char acc[10] = "xxxxxxxxx";
long sess = ic_universe_session(host, user, pass, acc, &status, NULL);
if (status == 0)
{
char sub_name[14] = "PRUEBA_XXXXXX";
long sub_name_len = 13;
unsigned char param1_txt[5] = "AAAA";
long size1 = 5;
long num_params = 2;
//void * FAR PASCAL ic_malloc ic_proto((LPLONG));
char* param1 = ic_malloc(&size1);
memcpy(param1, param1_txt, size1);
/* typedef struct icstring {
long len;
unsigned char * text;
} ICSTRING; */
ICSTRING icstr1;
icstr1.len = size1; icstr1.text = param1;
ICSTRING icstr2;
icstr2.len = 0;
ic_subcall(sub_name, &sub_name_len, &status, &num_params, &icstr1, &icstr2);
//void FAR PASCAL ic_free ic_proto((void *));
ic_free(icstr1.text);
ic_free(icstr2.text);
}
return EXIT_SUCCESS;
}
库可以释放并重新分配我传递给它的指针,所以这就是为什么我需要释放icstr1.text而不是ic_malloc的返回指针param1的原因。
在python中,类似的示例如下:
subrutina = 'PRUEBA_XXXXXX'
argumento = 'AAAA'
num_params = 2
argumentos_tipo = [c_char_p, POINTER(c_long), POINTER(c_long), POINTER(c_long)]
self.__U2_C_INTERFACE.ic_calloc.argtypes = [POINTER(c_long)]
self.__U2_C_INTERFACE.ic_free.argtypes = [ctypes.c_voidp]
self.__U2_C_INTERFACE.ic_subcall.argtypes = argumentos_tipo
sub_name_in = c_char_p(bytes(subrutina, self.__sistema_codificacion))
sub_name_len_in = c_long(len(subrutina))
num_params_len_in = c_long(num_params)
code = c_long(0)
p_in = [None] * num_params
mem_alloc = [c_char_p(0)] * num_params
byte_param = bytes(argumento, self.__sistema_codificacion)
byte_size = len(byte_param)
p_in[0] = ICString(c_long(0))
p_in[0].len = c_long(byte_size)
mem_alloc[0] = c_char_p(self.__U2_C_INTERFACE.ic_calloc(byref(c_long(byte_size + 1))))
tam = byte_size * sizeof(ctypes.c_char)
ctypes.memmove(mem_alloc[0], byte_param, tam)
p_in[0].text = mem_alloc[0]
p_in[1] = ICString(c_long(0))
self.__U2_C_INTERFACE.ic_subcall(sub_name_in,
byref(sub_name_len_in),
byref(code),
byref(num_params_len_in),
*[byref(n) for n in p_in])
if int(code.value) != 0:
err_msg = 'Error subrutina %s: %s' % (subrutina, UniverseConstants.error_message(code.value))
from pyuniverse.pyuniverse.UniverseExceptions import UniverseCommandException
raise UniverseCommandException(err_msg)
# copiar los resultados
for idx, parametro in enumerate(p_in):
print(p_in[idx].text)
# if p_in[idx].len > 0:
# temp = ctypes.cast(p_in[idx].text, ctypes.c_void_p)
# self.__U2_C_INTERFACE.ic_free(temp)
但是对ic_free的调用在堆中造成了麻烦:进程结束,退出代码-1073740940(0xC0000374)。这意味着“堆损坏异常0xC0000374”
我尝试使用pympler使用更多输入参数来跟踪内存使用情况。通过两个参数,我得到了:
types | # objects | total size
================================================ | =========== | ============
<class 'dict | 4 | 640 B
<class '_ctypes.PyCPointerType | 1 | 492 B
<class 'ctypes.CDLL.__init__.<locals>._FuncPtr | 4 | 480 B
<class 'builtin_function_or_method | 7 | 252 B
<class 'list | 5 | 236 B
<class 'tuple | 5 | 184 B
<class 'StgDict | 1 | 148 B
<class 'type | 0 | 144 B
<class 'str | 3 | 127 B
<class 'getset_descriptor | 2 | 80 B
<class 'weakref | 1 | 44 B
<class 'int | 1 | 16 B
并带有十个参数:
types | # objects | total size
================================================ | =========== | ============
<class 'dict | 4 | 640 B
<class '_ctypes.PyCPointerType | 1 | 492 B
<class 'ctypes.CDLL.__init__.<locals>._FuncPtr | 4 | 480 B
<class 'builtin_function_or_method | 7 | 252 B
<class 'list | 5 | 268 B
<class 'tuple | 5 | 184 B
<class 'StgDict | 1 | 148 B
<class 'type | 0 | 144 B
<class 'str | 11 | 401 B
<class 'getset_descriptor | 2 | 80 B
<class 'weakref | 1 | 44 B
<class 'int | 1 | 16 B
主要区别在于“ str”类:
Two params: <class 'str | 3 | 127 B
Ten params: <class 'str | 11 | 401 B
该内存将由python的垃圾收集器处理吗?我想念什么吗?我在pympler中看不到一些内存泄漏吗?