Kiểu Option<T>
trong Rust đem lại những lợi thế và khả năng đảm bảo an toàn bộ nhớ vượt trội so với cách mà C hay C++ sử dụng con trỏ null (NULL hay nullptr) để đại diện cho các tình huống “không có dữ liệu”. Rust thiết kế Option<T>
để giải quyết trực diện vấn đề lỗ hổng an toàn bộ nhớ gây ra bởi các thao thác phân giải con trỏ null hay “nullptr dereferencing”.
Trong các chương trình C/C++, khi một hàm có thể trả về một giá trị hoặc không có giá trị gì trả về, nó thường sẽ dùng con trỏ làm giá trị trả về. Và khi không có giá trị trả về thì nó sẽ trả về con trỏ null
. Hãy thử biên dịch và chạy chương trình dưới để thấy vấn đề của cách làm này.
#include <iostream>
#include <cstring>
const char* find_user(int id) { if (id == 1) return "Alice"; return nullptr; // không tìm thấy người dùng
}
int main() { const char* user = find_user(2); std::cout << "Độ dài tên: " << strlen(user) << std::endl; // Crash return 0;
}
Với tư tưởng thiết kế là một ngôn ngữ an toàn bộ nhớ, hay nói cách khác nếu đã biên dịch thành công thì sẽ không thể có lỗi bổ nhớ khi hoạt động, Rust đã triển khai trong hệ thống kiểu dữ liệu của mình một kiểu dữ liệu có tên Option<T>
. Kiểu dữ liệu này có hai khả năng giá trị, Some(T)
nếu có giá trị T
; và None nếu chẳng có giá trị gì. Kiểu này sẽ được sử dụng trong các tình huống như minh họa trong đoạn mã C++ ở trên. Đoạn mã sau sẽ minh họa việc này.
fn find_user(id: i32) -> Option<&'static str> { if id == 1 { Some("Alice") } else { None // không tìm thấy người dùng }
}
fn main() { let user = find_user(2); match user { Some(name) => println!("Độ dài tên: {}", name.len()), // Nếu tìm thấy None => println!("Không tìm thấy người dùng"), // Nếu không tìm thấy }
}
Đoạn mã trên nếu đã biên dịch thành công thì không thể có lỗi “Segmentation fault (core dump)” như phiên bản C/C++.
Chắc hẳn có bạn sẽ nói rằng từ C++17 đã có std::optional để xử lý an toàn những tình huống như thế này hay hoàn toàn có thể tự định nghĩa thêm một cấu trúc trong C để kiểm soát các giá trị con trỏ null trả về. Đúng, không sai, nhưng rất tiếc cả hai giải pháp này đều không được trình biên dịch C/C++ đảm bảo tính tuân thủ tuyệt đối trong việc kiểm tra tình huống null hay nói cách khác các lập trình viên hoàn toàn có thể quên không xử lý tình huống khi không có giá trị trả về hay giá trị trả về là null. Cái gì phải tự nhớ để thực hiện thì khả năng cao là sẽ bị bỏ sót, đặc biệt trong các chương trình lớn. Đó cũng chính là nguồn cơn của rất nhiều vụ tấn công mạng và làm anh em IT mất ngủ đêm hôm do sập hệ thống.
Hãy cùng RustDEV Vietnam tìm hiểu thêm về Option<T>
cũng như cách sử dụng nó khi lập trình Rust trong video #0001 Option≺T≻ - Sử dụng như thế nào? và #0002 Option≺T≻ - Nói thêm về an toàn bộ nhớ trên kênh Youtube RustDEV Vietnam.