面试题答案
一键面试- 初始化指针:
- 在使用裸指针之前,确保它被正确初始化。例如,如果是指向一个堆上分配的对象,使用
Box::into_raw
等方法来获取一个有效的指针,而不是随意构造一个未初始化的指针。
let boxed = Box::new(42); let raw_ptr = Box::into_raw(boxed);
- 在使用裸指针之前,确保它被正确初始化。例如,如果是指向一个堆上分配的对象,使用
- 确保指针有效性:
- 在使用指针前,检查指针是否为
null
。可以使用if ptr.is_null()
进行判断。
unsafe { if!raw_ptr.is_null() { // 进行指针操作 } }
- 在使用指针前,检查指针是否为
- 管理内存生命周期:
- 对于指向堆内存的指针,要清楚其生命周期。如果是通过
Box::into_raw
获取的指针,必须在合适的时候使用Box::from_raw
将所有权交回给Box
,以确保内存被正确释放。
let boxed = Box::new(42); let raw_ptr = Box::into_raw(boxed); unsafe { let new_box = Box::from_raw(raw_ptr); }
- 对于指向堆内存的指针,要清楚其生命周期。如果是通过
- 避免悬垂指针:
- 确保指针所指向的对象在指针使用期间不会被释放。如果对象的生命周期结束,要么重新分配内存并更新指针,要么确保指针不再被使用。例如,在函数返回时,不要返回指向局部变量的裸指针。
// 错误示例,返回指向局部变量的指针 // unsafe fn bad_fn() -> *const i32 { // let num = 42; // &num as *const i32 // }
- 内存泄漏检查:
- 仔细审查代码逻辑,确保所有分配的内存最终都被释放。在复杂数据结构中,确保每个元素的内存都被正确管理。例如,如果有一个链表,删除节点时要释放节点的内存。
- 使用RAII原则:
- 尽可能将裸指针封装在实现了
Drop
trait的结构体中,利用Rust的RAII(Resource Acquisition Is Initialization)机制来自动管理资源释放。
struct MyPtr { ptr: *mut i32, } impl Drop for MyPtr { fn drop(&mut self) { unsafe { if!self.ptr.is_null() { std::ptr::drop_in_place(self.ptr); std::alloc::dealloc(self.ptr as *mut u8, std::alloc::Layout::new::<i32>()); } } } }
- 尽可能将裸指针封装在实现了