[英]Python ctypes 'c_char_p' memory leak
我正在開發一個用於密碼學的 Python 庫。 我想通過使用 GMP 用 C++ 編寫主要類來優化我的庫。 我編寫了我的 C++ 類並編寫了extern
方法來使用主要的算術運算:加法、減法等......這些方法將結果返回為 char* 以避免轉換問題。 我構建了庫的 DLL,並在帶有 ctypes 的 Python 包裝器中聲明了方法。 我注意到在每次有大量數字的算術運算之后,內存呈指數增長。 我一直在尋找我的 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
。 這樣我使用DLL方法正確刪除a
,但我仍然有內存泄漏問題。 就好像 Python 垃圾收集器沒有正確c_char_p
類型的字符串的內存c_char_p
。 在之前的實現中,我只使用了 Python 和gmpy2
庫,因此所有數字都轉換為mpz
或mpq
。 我使用memory_profiler
包測試了內存消耗。 我創建了 40 個投影點類型的對象,定義在橢圓曲線上,我計算了i*P
的乘積, i
從 1 到gmpy2
總共使用了大約 70MB。 相反,將 ctypes 與 C++ 中的類一起使用,內存消耗上升到 1.5GB。 很明顯有問題,特別是當只有處理算術運算的基類發生變化時。 如何在沒有內存泄漏問題的情況下正確釋放內存? 我舉了一個用於計算算術運算的extern
方法的例子,但我已經檢查過問題僅在於通過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
對象的空間。
問題出在這一行:
res = ctypes.c_char_p(a.value)
這將創建的副本a.value
,並設置res
的c_char_p
指向副本。 但是Python不會對ctypes
指針做內存管理,所以副本會泄露!
如果將以上行替換為以下內容,則應修復泄漏:
res = bytes(memoryview(a.value))
這也會創建一個副本,但res
將是一個真正的 Python 對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.