如果域名网站用来做违法/爱站网怎么使用

如果域名网站用来做违法,爱站网怎么使用,手机版的网站开发,中央广播电视总台2023年元宵晚会喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 说句题外话,这篇文章一共5721个字,是我截至目前写的最长的一篇文章&a…

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
请添加图片描述
说句题外话,这篇文章一共5721个字,是我截至目前写的最长的一篇文章,看我这么努力,还不点赞、收藏加关注?
请添加图片描述

2.8.1. 显式析构函数的问题

添加显式析构函数时会遇到问题:

  • 当某一类型实现了Drop,在析构函数中无法将该类型的任何字段移出。因为在显式析构函数运行后,drop()仍会被调用,它接受&mut self,要求self的所有部分都没被移动。
  • Drop接收的是&mut self而不是self,因此Drop无法实现简单地调用显式析构函数并忽略其结果(因为Drop不拥有self)

以上一篇文章的例子为基础,如果我们加上既实现了Drop trait,又写了close方法:

use std::os::fd::AsRawFd;  
use std::fs::{File as StdFile, OpenOptions, metadata};  
use std::io::Error;  /// 一个表示文件句柄的类型  
struct File {  /// 文件名  name: String,  /// 文件描述符  fd: i32,  
}  impl File {  /// 一个构造函数,打开一个文件并返回一个 File 实例  fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  name: name.to_string(),  fd,  })  }  /// 一个显式的析构函数,关闭文件并返回任何错误  fn close(self) -> Result<(), Error> {  // 使用 FromRawFd 将 fd 转换回 File        let file: std::fs::File = unsafe {   std::os::unix::io::FromRawFd::from_raw_fd(self.fd)   };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  }  
}  //实现drop trait  
impl Drop for File {  fn drop(&mut self) {  let _ = self.close();  //调用close方法来丢弃  println!("File dropped");  }  
}  fn main() {  // 创建一个名为 "test.txt" 的文件,并写入一些内容  std::fs::write("test.txt", "Hello, world!").unwrap();  // 打开文件并获取 File 实例  let file: File = File::open("test.txt").unwrap();  // 打印文件名和 fd    println!("File name: {}, fd: {}", file.name, file.fd);  // 关闭文件并处理任何错误  match file.close() {  Ok(()) => println!("File closed successfully"),  Err(e) => println!("Error closing file: {}", e),  }  // 检查关闭后的文件大小  let metadata = metadata("test.txt").unwrap();  println!("File size: {} bytes", metadata.len());  
}

输出:

error[E0507]: cannot move out of `*self` which is behind a mutable reference--> src/main.rs:59:17|
59 |         let _ = self.close();  //调用close方法来丢弃|                 ^^^^ ------- `*self` moved due to this method call|                 ||                 move occurs because `*self` has type `File`, which does not implement the `Copy` trait|
note: `File::close` takes ownership of the receiver `self`, which moves `*self`--> src/main.rs:33:14|
33 |     fn close(self) -> Result<(), Error> {|              ^^^^
note: if `File` implemented `Clone`, you could clone the value--> src/main.rs:6:1|
6  | struct File {| ^^^^^^^^^^^ consider implementing `Clone` for this type
...
59 |         let _ = self.close();  //调用close方法来丢弃|                 ---- you could clone this value

报错信息显示无法从*self中移出值,因为它位于&mut self后面。

2.8.2. 解决方案

首先需要说明的是没有完美的解决方案,我们只能尽力弥补。


解决方案1:把结构体包装Option<T>里然后再套一层结构体

我们可以将顶层方案作为包装了Option<T>的新类型,这样Option<T>内部持有一个类型,这个类型包含所有的字段。

这个时候我们就需要两个析构函数,外边一个里面一个。在这两个析构函数中使用Option::take函数来获取数据所有权从而移除值。

由于内部类型没有实现Drop,所以你可以获取所有字段的所有权。

缺点:想在顶层类型上提供的所有方法,现在都必须添加通过Option<T>这层壳来获取内部类型上字段的代码。

我们在上文的代码例基础上进行修改:

步骤1:改掉File的定义,套一层壳

首先我们得把两个字段移到另一个结构体里,套在Option<T>中作为File结构体的字段

/// 一个表示文件句柄的类型  
struct InnerFile {  /// 文件名  name: String,  /// 文件描述符  fd: i32,  
}  /// 给InnerFile套了一个壳  
struct File {  /// 把InnerFile包装在Option<T>中  inner: Option<InnerFile>,  
}

步骤2:修改File上的方法

File上有两个方法,我们都需要添加通过Option<T>这层壳来获取内部类型上字段的代码。

首先是open方法:

/// 一个构造函数,打开一个文件并返回一个 File 实例  
fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  inner: Some( InnerFile {  name: name.to_string(),  fd,  })  })  
}
  • 由于这个代码只有返回值设计了File结构体,所以也只有返回值需要改

接下来是close方法:

/// 一个显式的析构函数,关闭文件并返回任何错误  
fn close(mut self) -> Result<(), Error> { // 记得self要变为mut self,否则take不了  // 使用模式匹配提取出字段的值  if let Some(inner) = self.inner.take() {  let name = inner.name;  let fd = inner.fd;  println!("Closing file: {} with fd: {}", name, fd);  // 使用 FromRawFd 将 fd 转换回 File        let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  } else {  // 如果inner字段是None,说明文件已经被关闭或丢弃,返回错误  Err(Error::new(  std::io::ErrorKind::Other,  "File is already closed",  ))  }  
}
  • 参数传进去之后先得通过模式匹配来获取字段的值
  • 如果如果inner字段是None,也就是模式匹配不成功的情况下,我们需要自己写一个错误返回

步骤3:修改Drop trait的实现

Drop::drop方法需要修改:

fn drop(&mut self) {  // 使用模式匹配获取字段值  if let Some(inner) = self.inner.take() {  let name = inner.name;  let fd = inner.fd;  println!("Dropping file: {} (fd: {})", name, fd);  // 使用 FromRawFd 将 fd 转换回 File        let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 丢弃file实例  drop(file);  } else {  // 如果inner字段是None的话,说明文件已经被丢弃或关闭,不做任何操作  }  
}
  • 参数传进去之后先得通过模式匹配来获取字段的值
  • 如果inner字段是None的话,说明文件已经被丢弃或关闭,不做任何操作

步骤4:微修主函数

主函数中需要提取字段值的地方需要修改:

fn main() {// ...前文无修改,已省略// 打印文件名和 fd (这里需要修改)  println!("File name: {}, fd: {}",   file.inner.as_ref().unwrap().name,  file.inner.as_ref().unwrap().fd  );// ...后文无修改,已省略
}
  • 原始类型是 Option<InnerFile>,调用.as_ref()后变成Option<&InnerFile>
  • 变成了Option<&InnerFile>再使用unwrap提取出来的值就是引用而不是所有的值
  • file.inner是一个Option<InnerFile>类型。而直接访问Option的值需要转移所有权或匹配处理(例如通过 take()unwrap()),这会销毁Option的内部值,所以得要as_ref

整体代码

use std::os::fd::AsRawFd;  
use std::fs::{File as StdFile, OpenOptions, metadata};  
use std::io::Error;  /// 一个表示文件句柄的类型  
struct InnerFile {  /// 文件名  name: String,  /// 文件描述符  fd: i32,  
}  /// 给InnerFile套了一个壳  
struct File {  /// 把InnerFile包装在Option<T>中  inner: Option<InnerFile>,  
}  impl File {  /// 一个构造函数,打开一个文件并返回一个 File 实例  fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  inner: Some( InnerFile {  name: name.to_string(),  fd,  })  })  }  /// 一个显式的析构函数,关闭文件并返回任何错误  fn close(mut self) -> Result<(), Error> { // 记得self要变为mut self,否则take不了  // 使用模式匹配提取出字段的值  if let Some(inner) = self.inner.take() {  let name = inner.name;  let fd = inner.fd;  println!("Closing file: {} with fd: {}", name, fd);  // 使用 FromRawFd 将 fd 转换回 File            let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  } else {  // 如果inner字段是None,说明文件已经被关闭或丢弃,返回错误  Err(Error::new(  std::io::ErrorKind::Other,  "File is already closed",  ))  }  }  
}  // 实现drop trait,用于在值离开作用域时运行的一些代码  
impl Drop for File {  fn drop(&mut self) {  // 使用模式匹配获取字段值  if let Some(inner) = self.inner.take() {  let name = inner.name;  let fd = inner.fd;  println!("Dropping file: {} (fd: {})", name, fd);  // 使用 FromRawFd 将 fd 转换回 File            let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 丢弃file实例  drop(file);  } else {  // 如果inner字段是None的话,说明文件已经被丢弃或关闭,不做任何操作  }  }  
}  fn main() {  // 创建一个名为 "test.txt" 的文件,并写入一些内容  std::fs::write("test.txt", "Hello, world!").unwrap();  // 打开文件并获取 File 实例  let file: File = File::open("test.txt").unwrap();  // 打印文件名和 fd (这里需要修改)  println!("File name: {}, fd: {}",   file.inner.as_ref().unwrap().name,  file.inner.as_ref().unwrap().fd  );  // 关闭文件并处理任何错误  match file.close() {  Ok(()) => println!("File closed successfully"),  Err(e) => println!("Error closing file: {}", e),  }  // 检查关闭后的文件大小  let metadata = metadata("test.txt").unwrap();  println!("File size: {} bytes", metadata.len());  
}

解决方案2:把字段包装在Option<T>

我们也可以保持结构体不变,把每个字段的值都套在Option<T>里,需要获取所有权使用时用Option::take就可以,需要引用时用.as_ref().unwrap()就可以。

如果类型具有合理的空值,那么效果很好。

缺点:如果你必须将几乎每个字段都包装在Option中,然后对这些字段的每次访问都进行匹配的unwrap就会使代码变得很繁琐。

我们在上文的代码例基础上进行修改:

步骤1:改掉File的定义

为每一个字段添加一层Option<T>

/// 一个表示文件句柄的类型  
struct File {  /// 文件名  name: Option<String>,  /// 文件描述符  fd: Option<i32>,  
}

步骤2:修改File上的方法

File上有两个方法,我们都需要添加通过Option<T>这层壳来获取内部类型上字段的代码。

首先是open方法:

/// 一个构造函数,打开一个文件并返回一个 File 实例  
fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  name: Some(name.to_string()),  fd: Some(fd),  })  
}
  • open方法的参数没有涉及到File结构体,所以接收参数部分不用修改
  • open方法的返回值涉及到了File,得为每个字段添上Some变体

其次是close方法:

/// 一个显式的析构函数,关闭文件并返回任何错误  
fn close(mut self) -> Result<(), Error> {  // 模式匹配,并使用std::mem::take取出name字段的值  if let Some(name) = std::mem::take(&mut self.name) {  //模式匹配,并使用std::mem::take取出fd字段的值  if let Some(fd) = std::mem::take(&mut self.fd) {// 打印println!("Closing file: {} with fd: {}", name, fd);// 使用 FromRawFd 将 fd 转换回 File            let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  } else {  // 如果fd字段是None,说明文件已经被关闭或丢弃,返回一个错误  Err(Error::new(  std::io::ErrorKind::Other,  "File descriptor already dropped or taken",  ))  }  } else {  // 如果name字段是None,说明文件已经被关闭或丢弃,返回一个错误  Err(Error::new(  std::io::ErrorKind::Other,  "File name already dropped or taken",  ))  }  
}
  • 参数要先经过模式匹配,并使用std::mem::take取出里面的值
  • 如果任意字段是None,说明文件已经被关闭或丢弃,返回一个错误

步骤3:修改Drop trait的实现

fn drop(&mut self) {  // 使用模式匹配获取字段值  if let Some(name) = self.name.take() {  if let Some(fd) = self.fd.take() {  println!("Dropping file: {} (fd: {})", name, fd);  // 使用 FromRawFd 将 fd 转换回 Filelet file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 丢弃file实例    drop(file);  } else {  // 如果fd字段是None,说明文件已经被关闭或丢弃,不做任何操作  }  } else {  // 如果name字段是None,说明文件已经被关闭或丢弃,不做任何操作  }  
}
  • 参数要先经过模式匹配,并使用std::mem::take取出里面的值
  • 如果任意字段是None,说明文件已经被关闭或丢弃,不做任何操作

步骤4:微修主函数

fn main() {// ...前文无修改,已省略// 打印文件名和 fd (这里需要修改)  println!("File name: {}, fd: {}",   file.name.as_ref().unwrap(),  file.fd.as_ref().unwrap()  );// ...后文无修改,已省略
}
  • 原始类型被Option<T>包裹,调用.as_ref()后获得里面值的引用
  • 变成了引用之后再使用unwrap提取出来的值就是引用而不是所有的值
  • 而直接访问Option的值需要转移所有权或匹配处理(例如通过 take()unwrap()),这会销毁Option的内部值,所以得要as_ref

整体代码

use std::os::fd::AsRawFd;  
use std::fs::{File as StdFile, OpenOptions, metadata};  
use std::io::Error;  /// 一个表示文件句柄的类型  
struct File {  /// 文件名  name: Option<String>,  /// 文件描述符  fd: Option<i32>,  
}  impl File {  /// 一个构造函数,打开一个文件并返回一个 File 实例  fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  name: Some(name.to_string()),  fd: Some(fd),  })  }  /// 一个显式的析构函数,关闭文件并返回任何错误  fn close(mut self) -> Result<(), Error> {  // 模式匹配,并使用使用std::mem::take取出name字段的值  if let Some(name) = std::mem::take(&mut self.name) {  //模式匹配,并使用使用std::mem::take取出fd字段的值  if let Some(fd) = std::mem::take(&mut self.fd) {// 打印println!("Closing file: {} with fd: {}", name, fd);// 使用 FromRawFd 将 fd 转换回 File                let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  } else {  // 如果fd字段是None,说明文件已经被关闭或丢弃,返回一个错误  Err(Error::new(  std::io::ErrorKind::Other,  "File descriptor already dropped or taken",  ))  }  } else {  // 如果name字段是None,说明文件已经被关闭或丢弃,返回一个错误  Err(Error::new(  std::io::ErrorKind::Other,  "File name already dropped or taken",  ))  }  }  
}  // 实现drop trait,用于在值离开作用域时运行的一些代码  
impl Drop for File {  fn drop(&mut self) {  // 使用模式匹配获取字段值  if let Some(name) = self.name.take() {  if let Some(fd) = self.fd.take() {  println!("Dropping file: {} (fd: {})", name, fd);  // 使用 FromRawFd 将 fd 转换回 Filelet file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(fd)  };  // 丢弃file实例    drop(file);  } else {  // 如果fd字段是None,说明文件已经被关闭或丢弃,不做任何操作  }  } else {  // 如果name字段是None,说明文件已经被关闭或丢弃,不做任何操作  }  }  
}  fn main() {  // 创建一个名为 "test.txt" 的文件,并写入一些内容  std::fs::write("test.txt", "Hello, world!").unwrap();  // 打开文件并获取 File 实例  let file: File = File::open("test.txt").unwrap();  // 打印文件名和 fd (这里需要修改)   println!("File name: {}, fd: {}",   file.name.as_ref().unwrap(),  file.fd.as_ref().unwrap()  );  // 关闭文件并处理任何错误  match file.close() {  Ok(()) => println!("File closed successfully"),  Err(e) => println!("Error closing file: {}", e),  }  // 检查关闭后的文件大小  let metadata = metadata("test.txt").unwrap();  println!("File size: {} bytes", metadata.len());  
}

方法3:将数据持有在ManuallyDrop类型内

将数据持有在ManuallyDrop类型内,它会解引用内部类型,不必再使用unwrap

drop中进行销毁时,可使用ManuallyDrop::take来获取所有权。

缺点:ManuallyDrop::take是不安全的,需要放在unsafe块中。

我们在上文的代码例基础上进行修改:

步骤1:改掉File的定义

为每一个字段添加一层Option<T>

/// 一个表示文件句柄的类型  
struct File {  /// 文件名  name: ManuallyDrop<String>,  /// 文件描述符  fd: ManuallyDrop<i32>,  
}

步骤2:修改File上的方法

File上有两个方法,我们都需要添加通过Option<T>这层壳来获取内部类型上字段的代码。

首先是open方法:

/// 一个构造函数,打开一个文件并返回一个 File 实例  
fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  name: ManuallyDrop::new(name.to_string()),  fd: ManuallyDrop::new(fd),  })  
}
  • open方法的参数没有涉及到File结构体,所以接收参数部分不用修改
  • open方法的返回值涉及到了File,每个字段都得用ManuallyDrop::new来传值

其次是close方法:

/// 一个显式的析构函数,关闭文件并返回任何错误  
fn close(mut self) -> Result<(), Error> {  // 使用std::mem::replace将name字段替换为一个空字符串,把原来的值给name  let name =   std::mem::replace(&mut self.name, ManuallyDrop::new("".to_string()));  // 使用std::mem::replace将fd字段替换为一个无效的值(-1),把原来的值给fd let fd =   std::mem::replace(&mut self.fd, ManuallyDrop::new(0));  // 打印  println!("Closing file: {:?} with fd: {:?}", name, fd);  // 使用 FromRawFd 将 fd 转换回 File    let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(*fd) //这里fd要先解引用  };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  
}
  • 使用std::mem::replacename字段替换为一个空字符串,把原来的值给name
  • 使用std::mem::replacefd字段替换为一个无效的值(-1),把原来的值给fd
  • std::os::unix::io::FromRawFd::from_raw_fd(*fd)中参数要先解引用,也就是写*fd

步骤3:修改Drop trait的实现

fn drop(&mut self) {  // 使用ManuallyDrop::take取出name字段的值,并检查是否是空字符串  let name = unsafe { ManuallyDrop::take(&mut self.name) };  // 使用ManuallyDrop::take取出fd字段的值,并检查是否是无效的值  let fd = unsafe { ManuallyDrop::take(&mut self.fd) };  //打印  println!("Dropping file: {:?} (fd: {:?})", name, fd);  // 如果fd字段不是无效的值,说明文件还没有被关闭或丢弃,需要执行丢弃操作  if fd != -1 || !name.is_empty() {  let file = unsafe { std::fs::File::from_raw_fd(fd) };  // 丢弃  drop(file);  }
}
  • 使用ManuallyDrop::take取出namefd字段的值,并检查是否是空字符串或无效的值
  • 如果fd字段不是无效的值(不是-1),或是name字段不是空字符串,就说明文件还没有被关闭或丢弃,需要执行丢弃操作
  • 其实这里不用两个判断条件(fd != -1 || !name.is_empty()),一个就够了,因为namefd字段的值的变化是一起的,一个无效就代表着整个结构体都还未被清理。

步骤4:微修主函数

fn main() {// ...前文无修改,已省略// 打印文件名和 fd (这里需要修改)  println!("File name: {}, fd: {}", *file.name, *file.fd);// ...后文无修改,已省略
}
  • 使用解引用来打印值

整体代码

use std::os::fd::{AsRawFd, FromRawFd};  
use std::fs::{File as StdFile, OpenOptions, metadata};  
use std::io::Error;  
use std::mem::ManuallyDrop;  /// 一个表示文件句柄的类型  
struct File {  /// 文件名  name: ManuallyDrop<String>,  /// 文件描述符  fd: ManuallyDrop<i32>,  
}  impl File {  /// 一个构造函数,打开一个文件并返回一个 File 实例  fn open(name: &str) -> Result<File, Error> {  // 使用 OpenOptions 打开文件,具备读写权限  let file: StdFile = OpenOptions::new()  .read(true)  .write(true)  .open(name)?;  // 获取文件描述符  let fd: i32 = file.as_raw_fd();  // 返回一个 File 实例  Ok(File {  name: ManuallyDrop::new(name.to_string()),  fd: ManuallyDrop::new(fd),  })  }  /// 一个显式的析构函数,关闭文件并返回任何错误  fn close(mut self) -> Result<(), Error> {  // 使用std::mem::replace将name字段替换为一个空字符串,把原来的值给name  let name =   std::mem::replace(&mut self.name, ManuallyDrop::new("".to_string()));  // 使用std::mem::replace将fd字段替换为一个无效的值(-1),把原来的值给fd  let fd =   std::mem::replace(&mut self.fd, ManuallyDrop::new(-1));  // 打印  println!("Closing file: {:?} with fd: {:?}", name, fd);  // 使用 FromRawFd 将 fd 转换回 File        let file: std::fs::File = unsafe {  std::os::unix::io::FromRawFd::from_raw_fd(*fd) //这里fd要先解引用  };  // 刷新文件数据到磁盘  file.sync_all()?;  // 将文件截断为 0 字节  file.set_len(0)?;  // 再次刷新文件  file.sync_all()?;  // 丢弃文件实例,它会自动关闭文件  drop(file);  // 返回成功  Ok(())  }  
}  // 实现drop trait,用于在值离开作用域时运行的一些代码  
impl Drop for File {  fn drop(&mut self) {  // 使用ManuallyDrop::take取出name字段的值,并检查是否是空字符串  let name = unsafe { ManuallyDrop::take(&mut self.name) };  // 使用ManuallyDrop::take取出fd字段的值,并检查是否是无效的值  let fd = unsafe { ManuallyDrop::take(&mut self.fd) };  //打印  println!("Dropping file: {:?} (fd: {:?})", name, fd);  // 如果fd字段不是无效的值,说明文件还没有被关闭或丢弃,需要执行丢弃操作  if fd != -1 || !name.is_empty() {  let file = unsafe { std::fs::File::from_raw_fd(fd) };  // 丢弃  drop(file);  }  }  
}  fn main() {  // 创建一个名为 "test.txt" 的文件,并写入一些内容  std::fs::write("test.txt", "Hello, world!").unwrap();  // 打开文件并获取 File 实例  let file: File = File::open("test.txt").unwrap();  // 打印文件名和 fd (这里需要修改)   
println!("File name: {}, fd: {}", *file.name, *file.fd);  // 关闭文件并处理任何错误  match file.close() {  Ok(()) => println!("File closed successfully"),  Err(e) => println!("Error closing file: {}", e),  }  // 检查关闭后的文件大小  let metadata = metadata("test.txt").unwrap();  println!("File size: {} bytes", metadata.len());  
}

三种方案的选择

这三种方案的选择要根据实际情况,通常第二个方案。但是如果真的字段太多要写的unwrap太多的话就需要考虑其他的方案。

如果代码足够简单,可以轻松检查代码的安全性,那么第三种ManuallyDrop方案也是非常好的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/896313.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一周学会Flask3 Python Web开发-Jinja2模板过滤器使用

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在Jinja2中&#xff0c;过滤器(filter)是一些可以用来修改和过滤变量值的特殊函数&#xff0c;过滤器和变量用一个竖线 | &a…

数据库 安装initializing database不通过

出现一下情况时&#xff1a; 处理方法&#xff1a; 将自己的电脑名称 中文改成英文 即可通过

嵌入式开发:傅里叶变换(5):STM32和Matlab联调验证FFT

目录 1. MATLAB获取 STM32 的原始数据 2. 将数据上传到电脑 3. MATLAB 接收数据并验证 STM32进行傅里叶代码 结果分析 STM32 和 MATLAB 联调是嵌入式开发中常见的工作流程&#xff0c;通常目的是将 STM32 采集的数据或控制信号传输到 MATLAB 中进行实时处理、分析和可视化…

微信小程序源码逆向 MacOS

前言 日常工作中经常会遇到对小程序的渗透测试&#xff0c;微信小程序的源码是保存在用户客户端本地&#xff0c;在渗透的过程中我们需要提取小程序的源码进行问题分析&#xff0c;本篇介绍如何在苹果电脑 MacOS 系统上提取微信小程序的源码。 0x01 微信小程序提取 在苹果电…

ubuntu-24.04.1-desktop 中安装 QT6.7

ubuntu-24.04.1-desktop 中安装 QT6.7 1 环境准备1.1 安装 GCC 和必要的开发包:1.2 Xshell 连接 Ubuntu2 安装 Qt 和 Qt Creator:2.1 下载在线安装器2.2 在虚拟机中为文件添加可执行权限2.3 配置镜像地址运行安装器2.4 错误:libxcb-xinerama.so.0: cannot open shared objec…

从最小依赖角度谈静态库与动态库的选择及配置策略

文章目录 1. 前言2. 静态库与动态库&#xff1a;依赖最小化的抉择2.1 静态库概述2.2 动态库概述2.3 依赖最小化角度的选择建议 3. 运行时库配置策略&#xff1a;/MT 与 /MD 的取舍3.1 /MT 与 /MD 的优劣比较3.2 配置选择的建议 4. 实际案例与配置示例4.1 静态库示例&#xff08…

【深度学习神经网络学习笔记(二)】神经网络基础

神经网络基础 神经网络基础前言1、Logistic 回归2、逻辑回归损失函数3、梯度下降算法4、导数5、导数计算图6、链式法则7、逻辑回归的梯度下降 神经网络基础 前言 Logistic 回归是一种广泛应用于统计学和机器学习领域的广义线性回归模型&#xff0c;主要用于解决二分类问题。尽…

002简单MaterialApp主题和Scaffold脚手架

002最简单的MaterialApp主题和Scaffold脚手架使用导航栏_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1RZ421p7BL?spm_id_from333.788.videopod.episodes&vd_source68aea1c1d33b45ca3285a52d4ef7365f&p1501.MaterialApp纯净的 /*MaterialApp 是主题,自带方向设…

DeepSeek开源周Day1:FlashMLA引爆AI推理性能革命!

项目地址&#xff1a;GitHub - deepseek-ai/FlashMLA 开源日历&#xff1a;2025-02-24起 每日9AM(北京时间)更新&#xff0c;持续五天&#xff01; ​ 一、开源周震撼启幕 继上周预告后&#xff0c;DeepSeek于北京时间今晨9点准时开源「FlashMLA」&#xff0c;打响开源周五连…

springboot志同道合交友网站设计与实现(代码+数据库+LW)

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本志同道合交友网站就是在这样的大环境下诞生&#xff0c;其可以帮助使用者在短时间内处理完毕庞大的数据信…

20250212:https通信

1:防止DNS劫持:使用 https 进行通信。 因为是SDK授权开发,需要尽量压缩so库文件和三方依赖。所以第一想法是使用 head only 的 cpp-httplib 进行开发。 cpp-httplib 需要 SSL 版本是 3.0及以上。但本地已经在开发使用的是1.0.2a版本,不满足需求。 方案1:升级OpenSSL 将Op…

VisionPro-PMA工具

VisionPro-PMA工具 模板匹配的核心概念 康耐视(Cognex)的VisionPro是一款广泛应用工业自动化的机器视觉软件平台&#xff0c;其模板匹配(Pattern Matching)功能是核心工具之一&#xff0c;常用与目标定位、特征识别和质量检测等场景。 模板匹配&#xff1a;通过预先定义的参…

2025最新最全【大模型学习路线规划】零基础入门到精通_大模型 开发 学习路线

第一阶段&#xff1a;基础理论入门 目标&#xff1a;了解大模型的基本概念和背景。 内容&#xff1a; 人工智能演进与大模型兴起。 大模型定义及通用人工智能定义。 GPT模型的发展历程。 第二阶段&#xff1a;核心技术解析 目标&#xff1a;深入学习大模型的关键技术和工…

使用CSS3DRenderer/CSS2DRenderer给模型上面添加html标签

先放一下预览图 主要使用css2dRender和css3dRender&#xff0c;添加图片和标签。 思路&#xff1a;使用css3dRender添加一个图片&#xff0c;然后获取的位置坐标&#xff0c;使用css3dRender添加一个文字标签&#xff0c;也设置这个位置坐标&#xff0c;此外z轴设置一个高度&a…

视频裂变加群推广分享引流源码

源码介绍 视频裂变加群推广分享引流源码 最近网上很火&#xff0c;很多人都在用&#xff0c;适合引流裂变推广 测试环境&#xff1a;PHP7.4(PHP版本不限制) 第一次访问送五次观看次数&#xff0c;用户达到观看次数后需要分享给好友或者群,好友必须点击推广链接后才会增加观看次…

python-leetcode-每日温度

739. 每日温度 - 力扣&#xff08;LeetCode&#xff09; class Solution:def dailyTemperatures(self, temperatures: List[int]) -> List[int]:n len(temperatures)answer [0] * nstack [] # 存储索引for i, temp in enumerate(temperatures):while stack and temperat…

deepseek sse流式输出

链接 semi-ui-vue聊天组件 - 可以用这个组件优化界面 sse服务端消息推送 webflux&webclient Hi-Dream-Blog - 参考这个博客&#xff0c;可以在后台将markdown语法转为html 文章目录 链接效果代码pom.xmlDeepSeekControllerWebConfigDeepSeekClientAiChatRequestAiChatM…

Linux时间日期类指令

1、data指令 基本语法&#xff1a; date &#xff1a; 显示当前时间date %Y : 显示当前年份date %m &#xff1a; 显示当前月份date %d &#xff1a; 显示当前哪一天date “%Y-%m-%d %H:%M:%S" &#xff1a; 显示年月日时分秒date -s 字符串时间 &#xff1a; 设置系统时…

SQLMesh 系列教程9- 宏变量及内置宏变量

SQLMesh 的宏变量是一个强大的工具&#xff0c;能够显著提高 SQL 模型的动态化能力和可维护性。通过合理使用宏变量&#xff0c;可以实现动态时间范围、多环境配置、参数化查询等功能&#xff0c;从而简化数据模型的开发和维护流程。随着数据团队的规模扩大和业务复杂度的增加&…

鹏哥c语言数组(初阶数组)

前言&#xff1a; 对应c语言视频54集 内容&#xff1a; 一维数组的创建 数组是一组相同元素的集合&#xff0c; 数组的创建方式 type_t就是数组的元素类型&#xff0c;const_n是一个常量表达式&#xff0c;用来指定数组的大小 c99标准之前的&#xff0c;数组的大小必须是…