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

使用raylib绑定的Rust代码出现STATUS_HEAP_CORRUPTION错误求助

问题原因分析

堆损坏错误(STATUS_HEAP_CORRUPTION)的核心原因是get_sound函数中使用了栈分配的数组作为Wave数据来源:

  • 栈上的data: [f32; 44100]在函数返回后会立即被销毁,但其指针被传递给了raylib的Wave结构体。
  • 当Sound::load_sound_from_wave尝试使用或复制该指针指向的内存时,栈内存已经被释放/覆盖,导致非法内存访问,触发系统的堆损坏检测。

此外,音频线程中存在两处次要问题:

  1. 循环中调用get_sound却不处理返回的Sound实例,会导致内存泄漏。
  2. 长时间持有Mutex锁可能引发死锁风险。
修复方案

1. 替换栈数组为堆分配的Vec

将栈上的固定数组改为Vec<f32>,确保Wave数据存储在堆内存中,生命周期可控:

fn get_sound(audio_info: AudioInfo) -> Sound {
    // 使用堆分配的Vec替代栈数组
    let mut data: Vec<f32> = vec![0.0; 44100];
    let mut x: f32 = 0.0;
    
    // 简化样本计算逻辑(可选,不影响功能)
    for i in 0..44100 {
        data[i] = (0..8)
            .map(|idx| slider_to_sample(x, audio_info.slider_positions[idx], 0.0, 1000.0))
            .sum();
        x += 1.0 / 44100.0;
    }

    // 构造原始Wave结构体,传递堆内存指针
    let wave = unsafe {
        Wave::from_raw(ffi::Wave {
            sampleCount: 44100,
            sampleRate: 44100,
            sampleSize: 32,
            channels: 1,
            data: data.as_mut_ptr() as *mut c_void,
        })
    };

    // 加载Sound,raylib会复制Wave数据到内部缓冲区
    let sound = Sound::load_sound_from_wave(&wave).unwrap();
    // 手动释放Wave,避免重复内存操作
    drop(wave);
    sound
}

2. 修复音频线程的内存泄漏与锁问题

修改音频线程逻辑,及时卸载不再使用的Sound,并缩短Mutex持有时间:

audio_thread = thread::spawn(move || {
    use raylib::audio::*;
    let mut rl_audio: RaylibAudio = RaylibAudio::init_audio_device();
    let mut sound: Sound = get_sound((*audio_info.lock().unwrap()).clone());
    
    loop {
        // 仅在判断退出条件时持有锁,避免长时间占用
        let should_close = {
            let info = audio_info.lock().unwrap();
            info.close
        };
        if should_close {
            break;
        }

        if rl_audio.get_sounds_playing() == 0 {
            rl_audio.play_sound_multi(&sound)
        } else {
            // 卸载旧Sound后再创建新的,避免内存泄漏
            rl_audio.unload_sound(sound);
            sound = get_sound((*audio_info.lock().unwrap()).clone());
        }
    }
    // 退出前卸载最后一个Sound
    rl_audio.unload_sound(sound);
})

3. 额外优化建议

  • 避免在循环中频繁创建Sound:如果滑块位置变化不频繁,可以只在滑块更新时重新生成Sound,减少性能开销。
  • 错误处理:将unwrap()替换为更健壮的错误处理逻辑(如match或if let),避免程序意外panic。
验证修复

完成上述修改后,栈内存不再被非法访问,raylib可以安全地处理音频数据,堆损坏错误应该会消失。同时内存泄漏和死锁风险也得到了缓解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:34:57