Tôi đang sử dụng mô-đun ctypes
trong python để tải một thư viện c được chia sẻ, chứa lưu trữ cục bộ luồng. Nó là một thư viện c khá lớn với một lịch sử lâu dài, rằng chúng tôi đang cố gắng để làm cho thread an toàn. Thư viện chứa rất nhiều biến và thống kê toàn cầu, vì vậy chiến lược ban đầu của chúng tôi hướng tới an toàn luồng đã được sử dụng lưu trữ cục bộ luồng. Chúng tôi muốn libarary của chúng tôi được nền tảng độc lập, và đã được biên dịch và thử nghiệm an toàn thread trên cả hai win32, win64 và 64-bit Ubuntu. Từ một quy trình thuần túy, dường như không có vấn đề gì.Rò rỉ bộ nhớ khi sử dụng thư viện được chia sẻ với bộ nhớ cục bộ qua ctypes trong chương trình python
Tuy nhiên trong python (2.6 và 2.7) trên win32 và trên Ubuntu, chúng tôi thấy rò rỉ bộ nhớ. Dường như lưu trữ cục bộ luồng không được phát hành đúng cách khi một chuỗi python chấm dứt. Hoặc ít nhất bằng cách nào đó quá trình python không "nhận biết" về việc bộ nhớ được giải phóng. Cùng một vấn đề cũng được nhìn thấy trong một chương trình C# trên win32 thực sự, nhưng nó không phải là hiện tại trên máy chủ thử nghiệm win64 của chúng tôi (chạy python 2,7 cũng).
vấn đề này có thể được sao chép với một ví dụ đồ chơi đơn giản như thế này:
Tạo một c-file chứa (trên linux/unix
loại bỏ __declspec(dllexport)
):
#include <stdio.h>
#include <stdlib.h>
void __declspec(dllexport) Leaker(int tid){
static __thread double leaky[1024];
static __thread int init=0;
if (!init){
printf("Thread %d initializing.", tid);
int i;
for (i=0;i<1024;i++) leaky[i]=i;
init=1;}
else
printf("This is thread: %d\n",tid);
return;}
Compile wit MINGW
trên cửa sổ/gcc trên linux như:
gcc -o leaky.dll
(hoặc leaky.so
) -shared the_file.c
Trên cửa sổ chúng tôi có thể đã biên soạn với Visual Studio, thay thế __thread
bằng __declspec(thread)
. Tuy nhiên trên win32 (lên đến winXP tôi tin), điều này không hoạt động nếu thư viện được nạp trong thời gian chạy với LoadLibrary
.
Bây giờ tạo ra một chương trình python như:
import threading, ctypes, sys, time
NRUNS=1000
KEEP_ALIVE=5
REPEAT=2
lib=ctypes.cdll.LoadLibrary("leaky.dll")
lib.Leaker.argtypes=[ctypes.c_int]
lib.Leaker.restype=None
def UseLibrary(tid,repetitions):
for i in range(repetitions):
lib.Leaker(tid)
time.sleep(0.5)
def main():
finished_threads=0
while finished_threads<NRUNS:
if threading.activeCount()<KEEP_ALIVE:
finished_threads+=1
thread=threading.Thread(target=UseLibrary,args=(finished_threads,REPEAT))
thread.start()
while threading.activeCount()>1:
print("Active threads: %i" %threading.activeCount())
time.sleep(2)
return
if __name__=="__main__":
sys.exit(main())
Đó là đủ để tạo lại lỗi. Nhập khẩu rõ ràng bộ thu gom rác, thực hiện collect gc.collect()
khi bắt đầu mỗi chuỗi mới không có tác dụng.
Trong một thời gian, tôi nghĩ rằng vấn đề phải làm với thời gian chạy không tương thích (python được biên dịch bằng Visual Studio, thư viện của tôi với MINGW
). Nhưng vấn đề cũng là trên Ubuntu, nhưng không phải trên một máy chủ win64, ngay cả khi thư viện được biên dịch chéo với MINGW
.
Hy vọng rằng mọi người đều có thể trợ giúp!
Chúc mừng, Simon Kokkendorff, Khảo sát quốc gia và địa chính của Đan Mạch.
xin vui lòng xem xét biết lỗi python http://bugs.python.org/issue6627 http://bugs.python.org/issue3757 –
Ông có thể giải phóng các biến bị rò rỉ của bạn về chủ đề gần gũi trong C? –
để khắc phục điều này, hãy thử sử dụng malloc và miễn phí để khởi tạo và loại bỏ mảng – pyCthon