Я занимаюсь разработкой библиотеки Python для криптографии. Я хотел оптимизировать свою библиотеку, написав основные классы на C ++ с GMP. Я написал свои классы C ++ и написал extern
методы для использования основных арифметических c операций: сложение, вычитание и т. Д. c ... Эти методы возвращают результаты в виде char *, чтобы избежать проблем приведения. Я собрал DLL своей библиотеки и объявил методы в оболочке Python с ctypes. Я заметил, что после каждой арифметической операции c с огромными числами память росла в геометрической прогрессии. Я искал проблемы в моей реализации C ++, но не было никаких проблем благодаря сборщику мусора C ++. Я искал возможное решение, поэтому обнаружил, что мне нужно реализовать метод C ++, чтобы освободить память для строки, созданной DLL. Поэтому я написал этот простой метод:
extern "C" {
__declspec(dllexport) void free_memory(char * n)
{
free(n);
}
...
}
Я реализовал этот код в оболочке Python, чтобы освободить память, выделенную DLL:
import os
import ctypes
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
NUMERIC = ctypes.CDLL(DIR_PATH + "/numeric.dll")
...
NUMERIC.free_memory.argtypes = [ctypes.c_void_p]
NUMERIC.free_memory.restype = None
def void_cast(n):
a = ctypes.cast(n, ctypes.c_char_p)
res = ctypes.c_char_p(a.value)
NUMERIC.free_memory(a)
return res
То же самое с res = ctypes.c_char_p (a.value)
Я создаю новую переменную, которая больше не указывает на a
. Таким образом, я правильно удаляю a
, используя метод DLL, но у меня все еще есть проблемы утечки памяти. Как будто сборщик мусора Python неправильно освобождает память для строк типа c_char_p
. В предыдущей реализации я использовал только Python и библиотеку gmpy2
, поэтому все числа были преобразованы в mpz
или mpq
. Я проверил потребление памяти с помощью пакета memory_profiler
. Я создал 40 объектов типа проективной точки, определенных на эллиптической кривой, и вычислил произведения i*P
, с i
от 1 до 40. С gmpy2
было использовано около 70 МБ. Вместо этого при использовании ctypes с классами в C ++ потребление памяти возросло до 1,5 ГБ. Очевидно, что что-то не так, особенно когда меняются только базовые классы, которые имеют дело с арифметическими c операциями. Как правильно освободить память без проблем с утечкой памяти? Я поместил пример метода extern
для вычисления арифметической операции c, но я уже проверил, что проблема заключается только в правильном освобождении памяти с помощью функции free_memory
и переназначении строки так, чтобы сборщик мусора Python освободит строку при необходимости.
extern "C" {
__declspec(dllexport) const char* rat_add(const char * n, const char * m)
{
return (RationalNum(n) + RationalNum(m)).getValue();
}
}
Заранее спасибо и хорошего дня.
PS: Ясно, что в C ++ я правильно реализовал метод деструктора, чтобы освободить пространство mpz_t
и mpq_t
созданные объекты.