裸指针的分类

  1. *mut T 可变裸指针
  2. *const T 不可变裸指针

    如何获取裸指针?

    1. 从引用获取

    1. struct A;
    2. let a = &A;
    3. let o: *const A = a as *const A;

    2. 堆上分配

    1. struct A;
    2. let a = A;
    3. let a: *const A = Box::into_raw(Box::new(a));

    3. 内存分配器

    1. GlobalAlloc::alloc

    裸指针的一些特性

    1. 不释放所指向的对象

    ```rust struct A;

impl Drop for A { fn drop(&mut self) { println!(“drop A…”); } }

fn main() { let a = A; let b = Box::into_raw(Box::new(a)); }

  1. 执行这段代码并不会打印drop A。换句话说,**释放裸指针并不会释放它所指向的对象**。裸指针b的释放不会同时释放其指向的内存结构。<br />补充:令Rust内存泄漏的几种方法:
  2. 1. Box::leak(Box::new(a))
  3. 1. mem::forget(a)
  4. 1. ManuallyDrop::new(a)
  5. 这几个底层都是ManuallyDrop,任何被这个struct封装的结构都不会被释放。
  6. <a name="v7134"></a>
  7. ## 2. 解引用裸指针是不安全的
  8. ```rust
  9. fn main() {
  10. let mut a: i32 = 99;
  11. add_one(&mut a as *mut i32);
  12. println!("{}",a);
  13. }
  14. fn add_one(pointer: *mut i32) {
  15. unsafe { *pointer += 1 };
  16. }
  17. // 100

3. 解引用不能move出指针

  1. struct A;
  2. fn main() {
  3. let a = A;
  4. let x = &a as *const A;
  5. // 这里报错
  6. let mm :A = unsafe { *x };
  7. }

read可以吗:

  1. struct A;
  2. fn main() {
  3. let a = A;
  4. let x = &a as *const A;
  5. // let mm:A = unsafe { *x };
  6. let mm:A = unsafe { x.read() };
  7. }

看起来没报错。我们看read这个函数的注释:

/// Reads the value from src without moving it. This leaves the /// memory in src unchanged.

实际上 read 也不会move原数据。

4. ZST

Box上的ZST的裸指针,打印出来地址是0x1,跟注释里描述的一样,Box::new对于 ZST 实际上是没有发生内存申请的。

裸指针该如何释放呢?

指向栈的裸指针

裸指针指向栈的:指针,内存也会随着栈帧一起释放。

指向堆上的裸指针

Box::into_raw 将返回堆上的裸指针,对于此类指针,内部是 ManuallyDrop ,会阻止堆上内存的释放。我们拿着这样的裸指针,咋释放呢?

1. 从裸指针还原回box
  1. fn main() {
  2. let b = Box::into_raw(Box::new(A));
  3. let o = unsafe { Box::from_raw(b) };
  4. }
  5. struct A;
  6. impl Drop for A {
  7. fn drop(&mut self) {
  8. println!("drop A");
  9. }
  10. }

如此还原Box后,Box释放,内存即释放。

2. 直接释放裸指针

先执行下struct的Drop,就是调用drop_in_place,然后调用dealloc释放内存。

  1. use std::{
  2. alloc::{dealloc, Layout},
  3. ptr::drop_in_place,
  4. };
  5. struct A;
  6. impl Drop for A {
  7. fn drop(&mut self) {
  8. println!("drop AA")
  9. }
  10. }
  11. fn main() {
  12. let a = Box::into_raw(Box::new(A));
  13. unsafe { drop_in_place(a) };
  14. unsafe { dealloc(a as *mut u8, Layout::new::<A>()) };
  15. }