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

Rust 裸指针代码无println!语句时运行结果异常原因咨询

核心问题成因

你的代码出现异常的根本原因是存在未定义行为(Undefined Behavior, UB),看似无关的println!改变运行结果是UB的典型表现。
具体悬垂指针的来源:

  • Rust中值发生移动时,其栈上内存地址会变更。你在Solution::new方法中将Solution实例创建在new的栈帧上,取当前栈上实例的list字段地址赋值给ptr后,又将整个Solution实例作为返回值移动到main的栈帧中,此时new栈帧的内存已经被回收,ptr存储的就是指向无效栈内存的悬垂指针,后续对该指针的所有读写操作都不符合Rust的内存安全规则。
  • 有无println!会改变程序运行时的栈帧布局:保留println!时,悬垂指针指向的内存恰好没有被其他数据覆盖,暂时能读到正确值;注释println!后,对应内存被其他数据覆盖,就会读到异常的垃圾数值。

此外你当前存储*const Option<Box<ListNode>>类型指针的设计本身就不稳定:只要Solution实例本身发生移动,所有指向self.list的指针都会再次变成悬垂状态。

修复方案

推荐直接存储指向堆上ListNode的裸指针,堆上内存的地址不会随结构体移动发生变更,可以彻底规避悬垂问题,参考实现如下:

// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
  pub val: i32,
  pub next: Option<Box<ListNode>>
}

impl ListNode {
  #[inline]
  fn new(val: i32) -> Self {
    ListNode {
      next: None,
      val
    }
  }
}

use rand;
use std::ptr::null;

struct Solution {
    list: Option<Box<ListNode>>,
    ptr: *const ListNode
}

impl Solution {
    fn new(head: Option<Box<ListNode>>) -> Self {
        let ptr = head.as_ref().map(|node| &**node as *const ListNode).unwrap_or(null());
        Self {
            list: head,
            ptr,
        }
    }
    
    fn get_random(&mut self) -> i32 {
        let mut jumps: u8 = rand::random();
        unsafe {
            while jumps > 0 {
                if let Some(next) = (*self.ptr).next.as_ref() {
                    self.ptr = &**next as *const ListNode;
                } else {
                    self.ptr = self.list.as_ref().map(|node| &**node as *const ListNode).unwrap();
                }
                jumps -= 1;
            }
            return (*self.ptr).val;
        }
    }
}

内容的提问来源于stack exchange,提问作者wangjun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 01:45:02