簡體   English   中英

Python ctypes 'c_char_p' 內存泄漏

[英]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庫,因此所有數字都轉換為mpzmpq 我使用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_tmpq_t對象的空間。

問題出在這一行:

res = ctypes.c_char_p(a.value)

這將創建的副本a.value ,並設置resc_char_p指向副本。 但是Python不會對ctypes指針做內存管理,所以副本會泄露!

如果將以上行替換為以下內容,則應修復泄漏:

res = bytes(memoryview(a.value))

這也會創建一個副本,但res將是一個真正的 Python 對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM