如何为含sysinfo::System字段的结构体正确实现new()方法?
问题描述
给定如下Rust结构体:
use sysinfo::{System, Pid, Process}; pub struct SystemInfo<'a> { sys: System, process: &'a Process, }
需要为该结构体实现new()方法,要求返回的SystemInfo对象满足:
sys字段为sysinfo::System实例process字段为当前运行应用对应的Process对象,且该字段依赖于sys字段
尝试以下代码时出现「引用临时值」错误:
pub fn new() -> Self { let sys = &System::new_all(); let process = sys.process(Pid::from(process::id() as usize)).expect("Failed to get process"); SystemInfo { sys, process, } }
请问该如何正确实现new()方法?
解决方案
错误原因分析
- 你错误地将
sys声明为临时System实例的引用(&System::new_all()),这个临时实例会在new()函数执行结束后被销毁,导致process引用的对象悬空,触发「引用临时值」错误。 - 更关键的是,你试图构建自引用结构体:结构体同时持有
System实例和该实例内部的Process引用。Rust的安全内存模型不允许这种结构,因为结构体移动时内部引用会失效。
推荐实现方案
最安全且符合Rust规范的做法是避免存储Process引用,改为存储当前进程的Pid,需要使用Process时从sys中动态获取:
use sysinfo::{System, Pid, Process}; use std::process; pub struct SystemInfo { sys: System, current_pid: Pid, } impl SystemInfo { pub fn new() -> Self { let mut sys = System::new_all(); // 刷新系统信息确保能获取到当前进程 sys.refresh_all(); let current_pid = Pid::from(process::id() as usize); // 提前验证进程存在,避免后续调用出错 sys.process(current_pid).expect("Failed to get current process"); SystemInfo { sys, current_pid, } } // 提供方法获取当前进程的引用 pub fn current_process(&self) -> &Process { self.sys.process(self.current_pid).expect("Current process not found") } }
若必须存储Process引用(不推荐)
如果一定要在结构体中存储Process引用,只能通过unsafe代码实现自引用结构体,这会绕过Rust的安全检查,需要自行保证内存安全:
use sysinfo::{System, Pid, Process}; use std::process; use std::ptr; pub struct SystemInfo { sys: System, process: *const Process, } impl SystemInfo { pub fn new() -> Self { let mut sys = System::new_all(); sys.refresh_all(); let current_pid = Pid::from(process::id() as usize); let process = sys.process(current_pid).expect("Failed to get current process"); let process_ptr = process as *const Process; SystemInfo { sys, process: process_ptr, } } pub fn current_process(&self) -> &Process { unsafe { // 必须保证sys未被修改,process_ptr始终有效 &*self.process } } } // 手动实现Send和Sync,需自行保证安全 unsafe impl Send for SystemInfo {} unsafe impl Sync for SystemInfo {}
注意:unsafe方案存在内存安全风险,若后续调用
sys的刷新方法可能导致Process引用失效,因此强烈推荐第一种方案。
内容的提问来源于stack exchange,提问作者passinger
相关产品推荐
相关产品推荐

