Tập 34: `unsafe` có biên giới — Ranh giới của quyền lực

Một ngôn ngữ lập trình hệ thống không thể sống trong một lâu đài pha lê tuyệt đối an toàn. Sẽ đến lúc nó phải viết driver, quản lý các trang bộ nhớ vật lý, hoặc gọi trực tiếp qua FFI đến một thư viện C. Ở những nơi đó, compiler không có cách nào chứng minh được tính đúng đắn. Nó bắt buộc phải giao lại quyền lực cho con người.

But DUY yêu cầu quyền lực đó phải được thực thi ở một nơi có ranh giới rõ ràng.

let ptr: *i32 = ...
unsafe {
  let val = *ptr;
}

Sprint 37 định hình ranh giới đó bằng từ khóa unsafe và effect unsafe. Mọi thao tác sử dụng raw pointer (*T), ép kiểu thô, hoặc gọi các hàm có thuộc tính unsafe đều bị cấm ngặt ở safe code. Nếu compiler phát hiện một dòng code chạm vào pointer nằm ngoài block unsafe { ... }, nó sẽ báo lỗi ngay lập tức.

Block unsafe không làm cho code của anh trở nên an toàn hơn. Nó chỉ làm một việc: cảnh báo cho người đọc và compiler biết rằng từ đây, các bảo đảm của ngôn ngữ bị nới lỏng. Nếu chương trình bị crash do undefined behavior, vùng nghi phạm được thu hẹp lại trong các khối được đánh dấu này, thay vì là toàn bộ hàng triệu dòng code của hệ thống.

Về mặt compiler, unsafe là một effect đặc biệt. Nó lan truyền giống như io hay alloc. Một hàm gọi code unsafe bên trong mà không bọc trong block unsafe thì bản thân hàm đó phải khai báo effect unsafe. Hợp đồng an toàn được giữ vững bằng cách ép mọi kẽ hở phải được khai báo rõ ràng.

Quyết định này giải phóng chúng tôi khỏi cái bẫy của sự hoàn hảo cực đoan. Chúng tôi chấp nhận rằng con người đôi khi thông minh hơn compiler ở một vài hot path phần cứng, nhưng con người phải ký tên vào biên bản bàn giao trách nhiệm bằng từ khóa unsafe. Đây chính là sự trưởng thành của một ngôn ngữ thực dụng: không phủ nhận bóng tối, mà chiếu đèn vào nó.


Bình luận (0)

Đang tải bình luận...