Rust使用AtomicPtr包裹Process出现pid异常及相关问题咨询
问题根因分析
你的第一套方案运行异常的核心原因是持有悬垂指针触发了未定义行为(UB),和Process的Send/Sync实现无关:
你在lazy_static初始化PROCESS1时,使用了&mut Process::new(process::id()).unwrap(),这是取了一个栈上临时Process实例的可变引用。该临时实例会在初始化表达式执行结束后自动销毁,你存入AtomicPtr的指针此时指向的是已经被回收的栈内存,属于悬垂指针。后续通过该指针访问内存的行为完全没有安全保障,读到的pid是内存被复用后的垃圾值,自然和实际进程id不符,严重时会直接触发段错误。
为什么取消PROCESS2注释后两套方案都正常运行
这是未定义行为的典型表现:新增PROCESS2的初始化、访问逻辑后,程序的栈布局、内存分配/使用顺序发生了变化,原本已经被释放的Process实例占用的内存刚好没有被其他数据覆盖,你碰巧读到了未被篡改的旧值。这完全是运行时的巧合,没有任何可靠性,调整编译优化等级、修改其他代码、升级Rust版本都可能让问题重新复现。
补充建议
- 如果你一定要用
AtomicPtr存储Process实例,应该将实例分配到堆上避免自动回收,初始化时修改为:
static ref PROCESS1 : AtomicPtr<Process> = AtomicPtr::new( Box::into_raw(Box::new(Process::new(process::id()).unwrap())) );
这样Process实例会被存放在堆上,内存不会被自动回收,指针不存在悬垂问题。
2. 你自行实现的ProcessWrapper确实是冗余实现,手动写unsafe impl Send/Sync反而会引入潜在风险:如果后续psutil版本升级,Process内部新增了不满足Sync约束的成员,你手动声明的特性会绕过编译器的线程安全检查,引发线程安全问题。
内容的提问来源于stack exchange,提问作者Forsworn
相关产品推荐
相关产品推荐

