Điều gì box x
thường sử dụng để cấp phát và bộ nhớ trống?
Câu trả lời là các chức năng được đánh dấu bằng các mục lang exchange_malloc
để phân bổ và exchange_free
để giải phóng. Bạn có thể xem việc triển khai những người trong thư viện chuẩn mặc định tại heap.rs#L112 và heap.rs#L125.
Trong khi kết thúc cú pháp box x
phụ thuộc vào các mục lang sau:
owned_box
trên một struct Box
để đóng gói các con trỏ được phân bổ. Cấu trúc này không cần thực hiện Drop
, nó được thực hiện tự động bởi trình biên dịch.
exchange_malloc
để cấp phát bộ nhớ.
exchange_free
để giải phóng bộ nhớ được phân bổ trước đó.
Điều này có thể được nhìn thấy một cách hiệu quả trong lang items chương của cuốn sách gỉ sử dụng no_std
ví dụ này:
#![feature(lang_items, box_syntax, start, no_std, libc)]
#![no_std]
extern crate libc;
extern {
fn abort() -> !;
}
#[lang = "owned_box"]
pub struct Box<T>(*mut T);
#[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
let p = libc::malloc(size as libc::size_t) as *mut u8;
// malloc failed
if p as usize == 0 {
abort();
}
p
}
#[lang = "exchange_free"]
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
libc::free(ptr as *mut libc::c_void)
}
#[start]
fn main(argc: isize, argv: *const *const u8) -> isize {
let x = box 1;
0
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
Chú ý cách Drop
đã không được thực hiện cho Box
struct? Vâng chúng ta hãy xem các LLVM IR tạo ra cho main
:
define internal i64 @_ZN4main20hbd13b522fdb5b7d4ebaE(i64, i8**) unnamed_addr #1 {
entry-block:
%argc = alloca i64
%argv = alloca i8**
%x = alloca i32*
store i64 %0, i64* %argc, align 8
store i8** %1, i8*** %argv, align 8
%2 = call i8* @_ZN8allocate20hf9df30890c435d76naaE(i64 4, i64 4)
%3 = bitcast i8* %2 to i32*
store i32 1, i32* %3, align 4
store i32* %3, i32** %x, align 8
call void @"_ZN14Box$LT$i32$GT$9drop.103617h8817b938807fc41eE"(i32** %x)
ret i64 0
}
Các allocate
(_ZN8allocate20hf9df30890c435d76naaE
) được gọi như mong đợi để xây dựng Box
, trong khi đó ... Nhìn kìa! Phương thức Drop
cho số Box
(_ZN14Box$LT$i32$GT$9drop.103617h8817b938807fc41eE
)! Hãy xem IR cho phương pháp này:
define internal void @"_ZN14Box$LT$i32$GT$9drop.103617h8817b938807fc41eE"(i32**) unnamed_addr #0 {
entry-block:
%1 = load i32** %0
%2 = ptrtoint i32* %1 to i64
%3 = icmp ne i64 %2, 2097865
br i1 %3, label %cond, label %next
next: ; preds = %cond, %entry- block
ret void
cond: ; preds = %entry-block
%4 = bitcast i32* %1 to i8*
call void @_ZN10deallocate20he2bff5e01707ad50VaaE(i8* %4, i64 4, i64 4)
br label %next
}
Có nó là, deallocate
(ZN10deallocate20he2bff5e01707ad50VaaE
) được gọi vào trình biên dịch tạo ra Drop!
Thông báo ngay cả trên standard library đặc điểm Drop
không được thực thi bởi mã người dùng. Thật vậy Box
là một chút của một cấu trúc kỳ diệu.
Vì vậy, hiện tại (trong quá trình thực hiện ở trên) 'hộp x' là cú pháp vị trí mới? – thirtythreeforty
@thirtythreeforty, vâng, đó là vị trí cú pháp mới hiện đang được mã hóa cứng để chỉ hoạt động với 'Box'. –
Vì vậy, cuối cùng 'Box' sẽ được xử lý không đặc biệt hơn bất kỳ loại nào tôi có thể tạo, và nó sẽ chỉ sử dụng các tính năng ngôn ngữ khác (post-1.0). – thirtythreeforty