2015-06-26 13 views
7

Vì đây là lần đầu tiên tôi lập trình hệ thống học tập, tôi đang gặp khó khăn trong việc bao quanh đầu các quy tắc. Bây giờ, tôi đã nhầm lẫn về rò rỉ bộ nhớ. Hãy xem xét một ví dụ. Nói, Rust đang ném một con trỏ (đến một chuỗi) mà Python sẽ bắt được.Làm thế nào để ngăn chặn rò rỉ bộ nhớ khi sử dụng `as_ptr()`?

Trong Rust, (tôi chỉ gửi con trỏ của CString)

use std::ffi::CString; 

pub extern fn do_something() -> *const c_char { 
    CString::new(some_string).unwrap().as_ptr() 
} 

Trong Python, (tôi dereferencing con trỏ)

def call_rust(): 
    lib = ctypes.cdll.LoadLibrary(rustLib) 
    lib.do_something.restype = ctypes.c_void_p 
    c_pointer = lib.do_something() 
    some_string = ctypes.c_char_p(c_pointer).value 

Bây giờ, câu hỏi của tôi là về giải phóng bộ nhớ. Tôi nghĩ rằng nó nên được giải phóng bằng Python, nhưng sau đó quyền sở hữu bật lên. Bởi vì, as_ptr dường như có một tham chiếu bất biến. Vì vậy, tôi đã nhầm lẫn về việc liệu tôi có nên giải phóng bộ nhớ trong Rust hoặc Python (hoặc cả hai?). Nếu nó sẽ là Rust, thì làm thế nào tôi nên giải phóng nó khi dòng điều khiển đã hạ cánh trở lại Python?

+1

Lưu ý rằng trong trường hợp này, không có ** rò rỉ bộ nhớ **. Thay vào đó, nó là một lỗi sử dụng sau khi miễn phí, mà thường là nhiều hơn nữa phá hoại. – Shepmaster

Trả lời

7

Hàm Rust của bạn do_something xây dựng tạm thời CString, đưa con trỏ vào đó, sau đó sẽ rơi xuống CString. *const c_char không hợp lệ kể từ khi bạn trả lại. Nếu bạn đang sử dụng hàng đêm, có thể bạn muốn CString#into_ptr thay vì CString#as_ptr, như trước đây tiêu thụ CString mà không cần deallocating bộ nhớ. Khi ổn định, bạn có thể mem::forget số CString. Sau đó, bạn có thể lo lắng về những người có nghĩa vụ phải giải phóng nó.

Giải phóng khỏi Python sẽ phức tạp hoặc không thể, vì Rust có thể sử dụng một trình cấp phát khác. Cách tiếp cận tốt nhất là phơi bày hàm Rust lấy con trỏ c_char, tạo CString cho con trỏ đó (thay vì sao chép dữ liệu vào phân bổ mới) và loại bỏ nó. Thật không may phần giữa (tạo ra các CString) dường như không thể ổn định cho bây giờ: CString::from_ptr là không ổn định.

Giải pháp thay thế sẽ chuyển (01 con trỏ đến) toàn bộ CString tới Python và cung cấp chức năng truy cập để lấy con trỏ char từ đó. Bạn chỉ cần đóng hộp CString và chuyển hộp thành con trỏ thô. Sau đó, bạn có thể có một chức năng khác mà chuyển con trỏ trở lại một hộp và cho phép nó thả.

+0

'CString' được biểu diễn dưới dạng' Hộp <[u8]> '; 'std :: raw :: Slice' (không ổn định) cho biết biểu diễn loại đó. Truyền qua lại có thể là cách tốt nhất nếu bạn muốn chuyển quyền sở hữu. –

+0

@ChrisMorgan 'CString' đã trở thành 'Hộp <[u8]>' cùng một lúc tôi đã thêm 'vào_ptr'; trước đó, nó là một 'Vec '. – Shepmaster

+0

@ChrisMorgan Điều này là không có giấy tờ mặc dù, và không giống như 'struct Box (* mut T)' nó không phải là rõ ràng rằng điều này sẽ không bao giờ thay đổi. Do đó, tôi rất mệt mỏi khi giới thiệu nó, đặc biệt là vì một 'from_ptr' /' from_ptr' ổn định có lẽ chỉ là hai bản phát hành. – delnan

Các vấn đề liên quan