You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含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()方法?

解决方案

错误原因分析

  1. 你错误地将sys声明为临时System实例的引用(&System::new_all()),这个临时实例会在new()函数执行结束后被销毁,导致process引用的对象悬空,触发「引用临时值」错误。
  2. 更关键的是,你试图构建自引用结构体:结构体同时持有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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:40:11